package com.yanqu.road.server.manager.activity.sonhai;

import com.alibaba.fastjson.JSONObject;
import com.yanqu.road.dao.impl.activity.sonhai.*;
import com.yanqu.road.entity.activity.commonteam.data.CommonTeamUserData;
import com.yanqu.road.entity.activity.sonhai.config.*;
import com.yanqu.road.entity.activity.sonhai.data.*;
import com.yanqu.road.entity.activity.sonhai.enums.*;
import com.yanqu.road.entity.activity.sonhai.param.*;
import com.yanqu.road.entity.log.cross.sonhai.*;
import com.yanqu.road.entity.player.CrossUserBaseInfo;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.entity.rank.yrank.UserYRank;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroup;
import com.yanqu.road.entity.union.activitygroup.UnionActivityGroupUser;
import com.yanqu.road.exception.BusinessException;
import com.yanqu.road.logic.helper.ActivityHelper;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.activity.SonHaiProto;
import com.yanqu.road.server.logic.MessageHelper;
import com.yanqu.road.server.manager.activity.ActivityMgr;
import com.yanqu.road.server.manager.activity.commonteam.CommonTeam;
import com.yanqu.road.server.manager.activity.commonteam.CommonTeamMgr;
import com.yanqu.road.server.manager.activity.sonhai.handler.IPlotTypeHandler;
import com.yanqu.road.server.manager.activity.sonhai.handler.entity.PlotTypeHandlerExploreReq;
import com.yanqu.road.server.manager.activity.sonhai.handler.entity.PlotTypeHandlerExploreResp;
import com.yanqu.road.server.manager.activity.sonhai.handler.impl.*;
import com.yanqu.road.server.manager.activity.sonhai.pb.SonHaiActivityPb;
import com.yanqu.road.server.manager.log.CrossAutoLogMgr;
import com.yanqu.road.server.manager.union.activitygroup.Cross2UnionActivityGroupMgr;
import com.yanqu.road.server.manager.user.CrossUserMgr;
import com.yanqu.road.server.manger.VipMgr;
import com.yanqu.road.server.protocol.GameErrorCode;
import com.yanqu.road.server.protocol.Protocol;
import com.yanqu.road.utils.*;
import com.yanqu.road.utils.date.DateHelper;
import com.yanqu.road.utils.plot.PlotUtil;
import com.yanqu.road.utils.plot.Point;
import com.yanqu.road.utils.property.Property;
import com.yanqu.road.utils.property.PropertyHelper;
import com.yanqu.road.utils.string.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

public class CrossSonHaiActivity {

    /**
     * logger
     */
    private static Logger logger = LogManager.getLogger(CrossSonHaiActivity.class.getName());

    /**
     * 活动锁
     */
    private ReentrantLock lock = new ReentrantLock();

    /**
     * 活动配置
     */
    private SonHaiConfig sonHaiConfig;

    /**
     * 分组ID
     */
    private int groupId;

    /**
     * 获取维度数据
     */
    private SonHaiActivityData activityData;

    /**
     * 玩家数据MAP
     */
    private Map<Long, CrossSonHaiUser> userMap = new ConcurrentHashMap<>();

    /**
     * 队伍数据MAP
     */
    private Map<Integer, CrossSonHaiTeam> teamMap = new ConcurrentHashMap<>();

    /**
     * 异兽蛋MAP
     */
    private Map<Integer, SonHaiEggData> eggMap = new ConcurrentHashMap<>();

    /**
     * 战斗争夺日志
     */
    private FixSizeLinkedList<SonHaiBattleLog> battleLogList = new FixSizeLinkedList<>(100);

    /**
     * 地块类型策略处理MAP
     */
    private Map<Integer, IPlotTypeHandler> plotTypeHandlerMap = new ConcurrentHashMap<>();

    /**
     * 构造
     * @param sonHaiConfig
     */
    public CrossSonHaiActivity(SonHaiConfig sonHaiConfig, int groupId) {
        this.groupId = groupId;
        this.sonHaiConfig = sonHaiConfig;
        //重载数据
        this.reloadData();
        //地块类型策略处理MAP
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_1.getType(), new PlotType1Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_2.getType(), new PlotType2Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_3.getType(), new PlotType3Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_4.getType(), new PlotType4Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_5.getType(), new PlotType5Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_6.getType(), new PlotType6Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_7.getType(), new PlotType7Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_8.getType(), new PlotType8Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_9.getType(), new PlotType9Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_10.getType(), new PlotType10Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_11.getType(), new PlotType11Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_12.getType(), new PlotType12Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_13.getType(), new PlotType13Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_14.getType(), new PlotType14Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_15.getType(), new PlotType15Handler());
        plotTypeHandlerMap.put(SonHaiPlotTypeEnum.PLOT_TYPE_16.getType(), new PlotType16Handler());
    }

    /**
     * 获取活动配置
     * @return
     */
    public SonHaiConfig getSonHaiConfig() {
        return sonHaiConfig;
    }

    /**
     * 刷新配置
     * @param sonHaiConfig
     */
    public void refreshConfig(SonHaiConfig sonHaiConfig) {
        this.sonHaiConfig = sonHaiConfig;
        //team对象刷新配置
        for (CrossSonHaiTeam team : teamMap.values()) {
            team.refreshConfig(sonHaiConfig);
        }
        //user对象刷新配置
        for (CrossSonHaiUser user : userMap.values()) {
            user.refreshConfig(sonHaiConfig);
        }
    }

    /**
     * 存储
     */
    public void save() {
        //活动数据存储
        SonHaiActivityDataDaoImpl activityDataDao = new SonHaiActivityDataDaoImpl();
        if (this.activityData.isInsertOption()) {
            activityDataDao.add(this.activityData);
        } else if (this.activityData.isUpdateOption()) {
            activityDataDao.update(this.activityData);
        }

        //蛋数据
        SonHaiEggDataDaoImpl eggDataDao = new SonHaiEggDataDaoImpl();
        for (SonHaiEggData eggData : this.eggMap.values()) {
            if (eggData.isInsertOption()) {
                eggDataDao.add(eggData);
            } else if (eggData.isUpdateOption()) {
                eggDataDao.update(eggData);
            }
        }

        //玩家数据存储
        SonHaiUserDataDaoImpl userDataDao = new SonHaiUserDataDaoImpl();
        SonHaiUserEggRewardDaoImpl eggRewardDao = new SonHaiUserEggRewardDaoImpl();
        for (CrossSonHaiUser user : this.userMap.values()) {
            if (user.isInsertOption()) {
                userDataDao.add(user);
            } else if (user.isUpdateOption()) {
                userDataDao.update(user);
            }
            //玩家兽蛋奖励存储
            for (SonHaiUserEggRewardData userEggRewardData : user.getUserEggRewardDataMap().values()) {
                if (userEggRewardData.isInsertOption()) {
                    eggRewardDao.add(userEggRewardData);
                } else if (userEggRewardData.isUpdateOption()) {
                    eggRewardDao.update(userEggRewardData);
                }
            }
        }

        //队伍数据存储
        for (CrossSonHaiTeam team : this.teamMap.values()) {
            team.save();
        }
    }

    /**
     * 重载数据
     */
    private void reloadData() {
        SonHaiUserDataDaoImpl userDataDao = new SonHaiUserDataDaoImpl();
        SonHaiTeamDataDaoImpl teamDataDao = new SonHaiTeamDataDaoImpl();
        SonHaiRegionDataDaoImpl regionDataDao = new SonHaiRegionDataDaoImpl();
        SonHaiPlotDataDaoImpl plotDataDao = new SonHaiPlotDataDaoImpl();
        SonHaiActivityDataDaoImpl activityDataDao = new SonHaiActivityDataDaoImpl();
        SonHaiUserEggRewardDaoImpl eggRewardDao = new SonHaiUserEggRewardDaoImpl();
        SonHaiEggDataDaoImpl eggDataDao = new SonHaiEggDataDaoImpl();

        //活动ID
        int activityId = this.sonHaiConfig.getActivityInfo().getActivityId();
        int groupId = this.groupId;

        //活动数据
        this.activityData = activityDataDao.getSonHaiActivityData(activityId, groupId);

        //蛋数据
       this.eggMap = eggDataDao.getSonHaiEggData(activityId, groupId);
       //构造下玩家占领的兽蛋MAP
       Map<Long, Map<Integer, SonHaiEggData>> userEggMap = new HashMap<>();
       for (SonHaiEggData eggData : this.eggMap.values()) {
           Map<Integer, SonHaiEggData> occupyEggMap = userEggMap.computeIfAbsent(eggData.getUserId(), k -> new HashMap<>());
           occupyEggMap.put(eggData.getId(), eggData);
       }

        //获取地块数据，k：队伍ID,k：区域ID,k：x_y
        Map<Integer, Map<Integer, Map<String, SonHaiPlotData>>> teamRegionPlotMap = plotDataDao.getSonHaiPlotDataMap(activityId, groupId);

        //获取区域数据，k：队伍ID,k：区域ID
        Map<Integer, Map<Integer, SonHaiRegionData>> regionDataMap = regionDataDao.getSonHaiRegionData(activityId, groupId);

        //攻击我的玩家地块MAP
        Map<Long, Map<Long, SonHaiPlotData>> attackUserPlotMap = new ConcurrentHashMap<>();

        //队伍数据
        Map<Integer, SonHaiTeamData> teamDataMap = teamDataDao.getSonHaiTeamDataMap(activityId, groupId);
        for (SonHaiTeamData teamData : teamDataMap.values()) {
            //队伍地块数据
            Map<Integer, Map<String, SonHaiPlotData>> regionPlotMap = teamRegionPlotMap.get(teamData.getTeamId());
            if (regionPlotMap == null) {
                logger.error("山海伏兽-加载队伍数据-队伍地块数据不存在：{}, {}", activityId, teamData.getTeamId());
                continue;
            }
            //队伍区域数据
            Map<Integer, SonHaiRegionData> teamRegionMap = regionDataMap.get(teamData.getTeamId());
            if (teamRegionMap == null) {
                logger.error("山海伏兽-加载队伍数据-队伍区域数据不存在：{}, {}", activityId, teamData.getTeamId());
                continue;
            }
            //区域注入地块
            for (SonHaiRegionData regionData : teamRegionMap.values()) {
                Map<String, SonHaiPlotData> plotDataMap = regionPlotMap.get(regionData.getRegionId());
                if (plotDataMap != null) {
                    //遍历地块
                    for (SonHaiPlotData plotData : plotDataMap.values()) {
                        regionData.addPlot(plotData);
                        if (plotData.getPvpUserId() > 0) {
                            Map<Long, SonHaiPlotData> attUserMap = attackUserPlotMap.computeIfAbsent(plotData.getPvpUserId(), k -> new ConcurrentHashMap<>());
                            attUserMap.put(plotData.getUserId(), plotData);
                        }
                        //判断地块是否有蛋
                        if (plotData.getEggId() > 0) {
                            SonHaiEggData eggData = this.eggMap.get(plotData.getEggId());
                            if (eggData != null) {
                                eggData.addAttackMeUserPlot(plotData);
                            }
                        }
                    }
                }
            }
            //创建队伍
            CrossSonHaiTeam team = new CrossSonHaiTeam(this.sonHaiConfig, teamData, teamRegionMap);
            this.teamMap.put(team.getTeamId(), team);
        }

        //玩家兽蛋奖励数据
        Map<Long, Map<Integer, SonHaiUserEggRewardData>> userEggRewardMap = eggRewardDao.getSonHaiUserEggRewardData(activityId, groupId);

        //玩家数据
        Map<Long, SonHaiUserData> userDataMap = userDataDao.getSonHaiUserDataMap(activityId, groupId);
        for (SonHaiUserData userData : userDataMap.values()) {
            //获取玩家队伍
            CrossSonHaiTeam team = this.teamMap.get(userData.getTeamId());
            if (team == null) {
                logger.error("山海伏兽-加载玩家数据-玩家队伍不存在：{}, {}", activityId, userData.getUserId());
                continue;
            }
            //玩家区域
            SonHaiRegionData regionData = team.getRegionMap().get(userData.getRegionId());
            //攻击我的玩家地块MAP
            Map<Long, SonHaiPlotData> attackMeUserPlotMap = attackUserPlotMap.getOrDefault(userData.getUserId(), new ConcurrentHashMap<>());
            //占领的兽蛋
            Map<Integer, SonHaiEggData> occupyEggMap = userEggMap.getOrDefault(userData.getUserId(), new ConcurrentHashMap<>());
            //兽蛋奖励MAP
            Map<Integer, SonHaiUserEggRewardData> userEggRewardDataMap = userEggRewardMap.getOrDefault(userData.getUserId(), new ConcurrentHashMap<>());
            //创建玩家
            CrossSonHaiUser user = new CrossSonHaiUser(this.sonHaiConfig, userData, regionData, attackMeUserPlotMap, userEggRewardDataMap, occupyEggMap);
            //队伍注入玩家
            team.addMember(user);
            this.userMap.put(user.getUserId(), user);
        }
    }

    public Logger getLogger() {
        return logger;
    }

    /**
     * 获取锁
     * @return
     */
    public ReentrantLock getLock() {
        return lock;
    }

    /**
     * 获取玩家
     * @param userId
     * @return
     */
    public CrossSonHaiUser getUser(long userId) {
        return userMap.get(userId);
    }

    /**
     * 获取队伍
     * @param teamId
     * @return
     */
    public CrossSonHaiTeam getTeam(int teamId) {
        return teamMap.get(teamId);
    }

    /**
     * 获取队伍MAP
     * @return
     */
    public Map<Integer, CrossSonHaiTeam> getTeamMap() {
        return teamMap;
    }

    /**
     * 获取兽蛋
     * @param eggId
     * @return
     */
    public SonHaiEggData getEgg(int eggId) {
        return this.eggMap.get(eggId);
    }

    /**
     * 获取兽蛋MAP
     * @return
     */
    public Map<Integer, SonHaiEggData> getEggMap() {
        return this.eggMap;
    }

    /**
     * 获取区域，根据玩家
     * @param userId
     * @return
     */
    public SonHaiRegionData getRegion(long userId) {
        CrossSonHaiUser user = this.getUser(userId);
        if (user != null) {
            return user.getRegionData();
        }
        return null;
    }

    /**
     * 同步队伍积分数据
     * @param userId
     */
    public void syncTeamScoreUpdate(long userId) {
        CrossSonHaiUser user = this.getUser(userId);
        if (user != null) {
            CrossSonHaiTeam team = this.getTeam(user.getTeamId());
            if (team != null) {
                long teamScore = team.getTeamScore();
                //通知区服，队伍积分变更
                team.syncMemberTeamUserScore(user.getServerId(), user.getUserId(), teamScore);
            }
        }
    }

    /**
     * 初始化蛋
     */
    private void initEgg() {
        if (this.eggMap != null && !this.eggMap.isEmpty()) {
            return;
        }
        //获取下总权重
        Map<Integer, SonHaiEggConfig> eggConfigMap = this.sonHaiConfig.getEggConfigMap();
        long allWeight = 0;
        for (SonHaiEggConfig eggConfig : eggConfigMap.values()) {
            allWeight += eggConfig.getWeight();
        }
        //蛋数量
        int eggNum = this.sonHaiConfig.getEggNum();
        //生成蛋
        int id = 1;
        Map<Integer, SonHaiEggData> eggMap = new ConcurrentHashMap<>();
        Set<Integer> eggNameIdSet = new HashSet<>(this.sonHaiConfig.getEggNameConfigMap().keySet());//蛋名称池子
        for (SonHaiEggConfig eggConfig : eggConfigMap.values()) {
            //生成的数量
            int num = (int) (eggNum * eggConfig.getWeight() / allWeight);
            for (int i = 0; i < num; i++) {
                //兽群
                SonHaiBeastGroupData beastGroupData = this.createBeastGroup(eggConfig.getMonsterList());
                //蛋的孵化时间
                long completeTime = this.sonHaiConfig.getFistDayEggRewardCompleteTime();
                //蛋名称
                if (eggNameIdSet.isEmpty()) {
                    //重置蛋名称池子
                    eggNameIdSet = new HashSet<>(this.sonHaiConfig.getEggNameConfigMap().keySet());
                }
                Integer eggNameId = RandomHelper.getRandomElement(eggNameIdSet);   //随机一个
                eggNameIdSet.remove(eggNameId);// 移除
                SonHaiEggNameConfig eggNameConfig = this.sonHaiConfig.getEggNameConfigMap().get(eggNameId);
                String eggName = eggNameConfig.getName();
                //创建蛋
                SonHaiEggData eggData = new SonHaiEggData(this.sonHaiConfig.getActivityInfo().getActivityId(),
                        this.groupId,
                        id,
                        eggConfig.getId(),
                        eggName,
                        beastGroupData,
                        completeTime
                );
                eggMap.put(id, eggData);
                id++;
            }
        }
        this.eggMap = eggMap;
    }

    /**
     * 通知区服同步vip均值
     */
    public void notifyServerSyncVipPower() {
        //获取区服
        Set<Long> serverIdSet = this.getServerIdSet();
        if (serverIdSet == null || serverIdSet.isEmpty()) {
            return;
        }
        for (long serverId : serverIdSet) {
            //已经有值，不再同步
            if (this.activityData.getServerAvePowerMap().containsKey(serverId)) {
                continue;
            }
            //发送【通知区服同步vip均值】消息
            this.sendNotifyServerSyncVipPowerMsg(serverId);
        }
    }

    /**
     * 获取区服ID集合
     * @return
     */
    private Set<Long> getServerIdSet() {
        //获取区服
        UnionActivityGroup groupData = Cross2UnionActivityGroupMgr.getGroupData(this.activityData.getActivityId(), this.groupId);
        if (groupData != null) {
            //分组活动
            return groupData.getServerSet();
        }
        logger.error("山海伏兽-获取区服ID集合-分组数据不存在：{},{}", this.activityData.getActivityId(), this.groupId);
        return null;
    }

    /**
     * 发送【通知区服同步vip均值】消息
     * @param serverId
     */
    private void sendNotifyServerSyncVipPowerMsg(long serverId) {
        logger.info("山海伏兽-通知区服同步vip均值-start：{},{},{}", this.activityData.getActivityId(), this.groupId, serverId);
        SonHaiProto.SonHaiNotifyServerSyncVipPowerFromCrossMsg.Builder builder = SonHaiProto.SonHaiNotifyServerSyncVipPowerFromCrossMsg.newBuilder();
        builder.setActivityId(this.activityData.getActivityId());
        builder.setGroupId(this.groupId);
        MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(Protocol.S_SON_HAI_NOTIFY_SERVER_SYNC_VIP_AVE_FROM_CROSS, builder));
        logger.info("山海伏兽-通知区服同步vip均值-end：{}", serverId);
    }

    /**
     * 接收区服上报的vip战力数据
     * @param serverId
     * @param reqMsg
     */
    public void receiveServerVipPower(long serverId, SonHaiProto.SonHaiCrossNotifyVipPowerReqMsg reqMsg) {
        logger.info("山海伏兽-接收区服上报的vip战力数据-start：{}", serverId);
        Map<Integer, SonHaiVipAvePowerData> serverVipAveMap = new ConcurrentHashMap<>();
        for (SonHaiProto.SonHaiVipNumPowerData vipPowerData : reqMsg.getVipPowerDataList()) {
            int vipLevel = vipPowerData.getVipLevel();
            serverVipAveMap.put(vipLevel, new SonHaiVipAvePowerData(vipLevel, vipPowerData.getAveAPower()));
        }
        this.activityData.addServerAvePowerMap(serverId, serverVipAveMap);
        //所有区服上报完毕后，计算一下vip分布的战力均值
        Set<Long> serverSet = this.getServerIdSet();
        if (serverSet == null || serverSet.isEmpty()) {
            return;
        }
        if (this.activityData.getServerAvePowerMap().size() == this.getServerIdSet().size()) {
            //构建vip战力均值MAP
            this.createVipAvePowerMap();
            //初始化蛋蛋
            this.initEgg();
        }
        logger.info("山海伏兽-接收区服上报的vip战力数据-end：{}", serverId);
    }

    /**
     * 构建vip战力均值MAP
     */
    private void createVipAvePowerMap() {
        Map<Long, Map<Integer, SonHaiVipAvePowerData>> serverVipPower = this.activityData.getServerAvePowerMap();
        //k:vip等级，v：战力数据
        Map<Integer, SonHaiVipPowerData> allPowerMap = new HashMap<>();
        for (Map<Integer, SonHaiVipAvePowerData> vipPowerMap : serverVipPower.values()) {
            for (SonHaiVipAvePowerData item : vipPowerMap.values()) {
                SonHaiVipPowerData info = allPowerMap.computeIfAbsent(item.getVipLevel(), k -> new SonHaiVipPowerData(item.getVipLevel(), 0, 0));
                info.setNum(info.getNum() + 1);
                info.setPower(info.getPower() + item.getAvePower());
            }
        }
        //k:vip等级,v:战力均值
        Map<Integer, Long> powerAveMap = new HashMap<>();
        for (SonHaiVipPowerData powerData : allPowerMap.values()) {
            long avePower = powerData.getPower() / powerData.getNum();
            powerAveMap.put(powerData.getVipLevel(), avePower);
        }

        //第一步：补齐数据为0的值
        int maxVipLevel = VipMgr.getMaxVipLv();//最大vip等级
        List<Long> vipPowerList = new ArrayList<>();
        for (int vipLevel = 0; vipLevel <= maxVipLevel; vipLevel++) {
            Long avePower = powerAveMap.get(vipLevel);
            if (avePower == null) {
                //vip等级没有值的情况
                if (vipLevel == 0) {
                    //vip0没有值的情况，取保底值
                    avePower = this.sonHaiConfig.getMonsterPowerMin();
                } else {
                    //vip1-vip15没有值的情况
                    long m1 = powerAveMap.getOrDefault(vipLevel - 1, 0L);
                    avePower = m1 * this.sonHaiConfig.getMonsterPowerParamByVipLevel(vipLevel) / 1000;
                }
                powerAveMap.put(vipLevel, avePower);
            }
            vipPowerList.add(avePower);
        }

        //第二步：排序
        Collections.sort(vipPowerList);
        Map<Integer, Long> fixPowerAveMap = new HashMap<>();
        for (int i = 0; i < vipPowerList.size(); i++) {
            fixPowerAveMap.put(i, vipPowerList.get(i));
        }
        this.activityData.setVipAvePowerMap(fixPowerAveMap);

//        //第一步：修正vip战力均值
//        Map<Integer, Long> fixPowerAveMap = new HashMap<>();
//        for (Map.Entry<Integer, Long> entry : powerAveMap.entrySet()) {
//            int vipLevel = entry.getKey();
//            long avePower = entry.getValue();
//            long m1 = powerAveMap.getOrDefault(vipLevel - 1, 0L);
//            long m2 = powerAveMap.getOrDefault(vipLevel + 1, 0L);
//            long value2 = (m1 + m2) / 2;
//            long targetValue = Math.max(avePower, value2);
//            fixPowerAveMap.put(vipLevel, targetValue);
//        }
//
//        //第二步：补齐VIP均值
//        int maxVipLevel = VipMgr.getMaxVipLv();//最大vip等级
//        for (int vipLevel = 0; vipLevel <= maxVipLevel; vipLevel++) {
//            Long avePower = fixPowerAveMap.get(vipLevel);
//            if (avePower == null) {
//                //vip等级没有值的情况
//                if (vipLevel == 0) {
//                    //vip0没有值的情况，取保底值
//                    avePower = this.sonHaiConfig.getMonsterPowerMin();
//                } else {
//                    //vip1-vip15没有值的情况
//                    long m1 = fixPowerAveMap.getOrDefault(vipLevel - 1, 0L);
//                    avePower = m1 * this.sonHaiConfig.getMonsterPowerParamByVipLevel(vipLevel) / 1000;
//                }
//            } else {
//                if (vipLevel != 0) {
//                    //vip等级有值的情况
//                    long m1 = fixPowerAveMap.getOrDefault(vipLevel - 1, 0L);
//                    long value1 = m1 * this.sonHaiConfig.getMonsterPowerParamByVipLevel(vipLevel) / 1000;
//                    if (avePower < m1) {
//                        avePower = value1;
//                    } else {
//                        avePower = Math.min(avePower, value1);
//                    }
//                }
//            }
//            fixPowerAveMap.put(vipLevel, avePower);
//        }
//        this.activityData.setVipAvePowerMap(fixPowerAveMap);
    }

    /**
     * 活动结束-更新区服队伍积分定时任务
     */
    public synchronized void syncUpdateTeamScore() {
        if (this.activityData.getUpdateTeamScoreTime() > 0) {
            return;
        }
        //判断活动是否结束
        long now = System.currentTimeMillis();
        if (now > this.sonHaiConfig.getActivityInfo().getEndTime() * 1000) {
            logger.info("山海伏兽-活动结束-更新区服队伍积分定时任务-start");
            //设置一下，处理时间
            this.activityData.setUpdateTeamScoreTime(System.currentTimeMillis());
            //同步区服玩家更新队伍积分（为保证活动期间未登录玩家队伍积分最新）
            Map<Long, List<SonHaiProto.SonHaiSyncTeamScoreUserItem.Builder>> serverUserScoreMap = new HashMap<>();
            for (CrossSonHaiTeam team : teamMap.values()) {
                long teamScore = team.getTeamScore();
                if (teamScore <= 0) {
                    continue;
                }
                for (CrossSonHaiUser user : team.getMemberMap().values()) {
                    List<SonHaiProto.SonHaiSyncTeamScoreUserItem.Builder> userScoreList = serverUserScoreMap.computeIfAbsent(user.getServerId(), k -> new ArrayList<>());
                    SonHaiProto.SonHaiSyncTeamScoreUserItem.Builder builder = SonHaiProto.SonHaiSyncTeamScoreUserItem.newBuilder();
                    builder.setUserId(user.getUserId());
                    builder.setTeamScore(teamScore);
                    userScoreList.add(builder);
                }
            }
            //同步游戏服更新玩家队伍积分
            for (Map.Entry<Long, List<SonHaiProto.SonHaiSyncTeamScoreUserItem.Builder>> entry : serverUserScoreMap.entrySet()) {
                long serverId = entry.getKey();
                List<SonHaiProto.SonHaiSyncTeamScoreUserItem.Builder> userScoreList = entry.getValue();
                SonHaiProto.SonHaiSyncTeamScoreFromCrossReqMsg.Builder builder = SonHaiProto.SonHaiSyncTeamScoreFromCrossReqMsg.newBuilder();
                builder.setActivityId(this.activityData.getActivityId());
                for (SonHaiProto.SonHaiSyncTeamScoreUserItem.Builder item : userScoreList) {
                    builder.addUsers(item);
                }
                MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(Protocol.S_SON_HAI_SYNC_TEAM_SCORE_END_ACTIVITY_FROM_CROSS, builder));
            }
            logger.info("山海伏兽-活动结束-更新区服队伍积分定时任务-end");
        }
    }

    /**
     * 每日结算兽蛋奖励
     */
    public void dailySettleEggReward() {
        try {
            //加锁-活动，设置5秒超时
            if (!this.getLock().tryLock(5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-每日结算兽蛋奖励-加锁-活动-超时：{}", this.activityData.getActivityId());
                return;
            }
            long now = System.currentTimeMillis();
            //22点05分结算
            long canResetTime = DateHelper.getDateForTime(22, 5, 0);
            if (canResetTime > now) {
                //还未到结算时间
                return;
            }
            //判断是否可结算
            long eggResetTime = this.activityData.getEggResetTime();
            boolean sameDay = DateHelper.checkTimeOneDay(now, eggResetTime);
            if (sameDay) {
                //今天已经结束过
                return;
            }
            logger.info("山海伏兽-每日结算兽蛋奖励-start：{}", new Date());
            //遍历蛋蛋
            Set<Long> syncUserIds = new HashSet<>();
            for (SonHaiEggData eggData : this.eggMap.values()) {
                //蛋奖励注入玩家
                if (eggData.getUserId() > 0 && System.currentTimeMillis() >= eggData.getCompleteTime()) {//有玩家 && 孵化时间已到
                    CrossSonHaiUser user = this.userMap.get(eggData.getUserId());
                    if (user != null) {
                        //添加蛋奖励
                        user.addUserEggRewardData(eggData, this.activityData);
                        syncUserIds.add(user.getUserId());
                    }
                }
                //重置蛋
                eggData.reset(true);
            }
            //设置下结算时间
            this.activityData.setEggResetTime(now);
            //同步下玩家数据
            for (long userId : syncUserIds) {
                CrossSonHaiUser user = this.getUser(userId);
                if (user != null) {
                    //同步玩家数据
                    user.syncUserData(false);
                    //同步兽蛋奖励红点
                    user.syncRedDotMsg(SonHaiRedDotTypeEnum.TYPE_HAVE, SonHaiRedDotTypeEnum.TYPE_NULL, SonHaiRedDotTypeEnum.TYPE_NULL);
                }
            }
            logger.info("山海伏兽-每日结算兽蛋奖励-end：{}", new Date());

            //判断活动是的在领奖期
            if (System.currentTimeMillis() / 1000 > this.sonHaiConfig.getActivityInfo().getEndTime()) {
                logger.info("山海伏兽-活动结束玩家重置地块，补发奖励-start：{}", new Date());
                for (CrossSonHaiTeam team : this.teamMap.values()) {
                    Set<Integer> regionIds = new HashSet<>(team.getRegionMap().keySet());
                    for (int regionId : regionIds) {
                        //删除区域。那些已镇伏，未领取的奖励，通过邮件补发
                        team.removeRegion(regionId);
                    }
                }
                logger.info("山海伏兽-活动结束玩家重置地块，补发奖励-end：{}", new Date());
            }
        } catch (InterruptedException e) {
            logger.error("山海伏兽-每日结算兽蛋奖励-tryLock报错：{}", e);
        } finally {
            this.getLock().unlock();
        }
    }

    /**
     * 补发玩家蛋蛋奖励
     */
    public void bfEggReward() {
        long now = System.currentTimeMillis();
        //判断活动是否结束
        if (now <= this.sonHaiConfig.getActivityInfo().getEndShowTime() * 1000) {
            return;
        }
        //判断奖励是否已经补发
        if (this.activityData.getBfEggRewardTime() > 0) {
            return;
        }
        try {
            //加锁-活动，设置5秒超时
            if (!this.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-补发蛋蛋奖励-加锁-活动-超时：{}", this.activityData.getActivityId());
                return;
            }
            logger.info("山海伏兽-补发蛋蛋奖励-start");
            Map<Long, List<SonHaiBfEggReward>> userEggRewardMap = new HashMap<>();
            //遍历玩家，是否有未领取奖励
            for (CrossSonHaiUser user : this.userMap.values()) {
                Property property = new Property();
                for (SonHaiUserEggRewardData rewardData : user.getUserEggRewardDataMap().values()) {
                    if (rewardData.getRewardFlag() == SonHaiRewardFlagEnum.GET_NOT.getType()) {
                        Property reward = PropertyHelper.parseStringToProperty(rewardData.getReward());
                        property.addProperty(reward);
                        //设置奖励已领取
                        rewardData.setRewardFlag(SonHaiRewardFlagEnum.GET_YES.getType());
                        rewardData.setRewardTime(System.currentTimeMillis());
                    }
                }
                if (!property.isNothing()) {
                    SonHaiBfEggReward userReward = new SonHaiBfEggReward();
                    userReward.setUserId(user.getUserId());
                    userReward.setReward(property);
                    List<SonHaiBfEggReward> serverRewardList = userEggRewardMap.computeIfAbsent(user.getServerId(), k -> new ArrayList<>());
                    serverRewardList.add(userReward);
                }
            }
            logger.info("山海伏兽-补发蛋蛋奖励-补发奖励详情：{}", JSONObject.toJSONString(userEggRewardMap));
            //设置补发时间
            this.activityData.setBfEggRewardTime(now);
            //遍历区服，补发玩家蛋蛋奖励
            for (Map.Entry<Long, List<SonHaiBfEggReward>> entry : userEggRewardMap.entrySet()) {
                long serverId = entry.getKey();
                List<SonHaiBfEggReward> userRewardList = entry.getValue();
                SonHaiProto.SonHaiBfEggRewardFromCrossMsg.Builder builder = SonHaiProto.SonHaiBfEggRewardFromCrossMsg.newBuilder();
                for (SonHaiBfEggReward userReward : userRewardList) {
                    SonHaiProto.SonHaiBfEggRewardItem.Builder item = SonHaiProto.SonHaiBfEggRewardItem.newBuilder();
                    item.setUserId(userReward.getUserId());
                    item.setReward(PropertyHelper.parsePropertyToString(userReward.getReward()));
                    builder.addUserEggReward(item);
                }
                //通知区服，补发奖励
                MessageHelper.sendPacket(serverId, 0, YanQuMessageUtils.buildMessage(Protocol.S_SON_HAI_BF_EGG_REWARD_FROM_CROSS, builder));
            }
            logger.info("山海伏兽-补发蛋蛋奖励-END");
        } catch (InterruptedException e) {
            logger.error("山海伏兽-补发蛋蛋奖励-tryLock报错：{}", e);
        } finally {
            this.getLock().unlock();
        }
    }

    /**
     * 初始化队伍
     * @param commonTeam
     * @return
     */
    private CrossSonHaiTeam initTeam(CommonTeam commonTeam, String language) throws BusinessException {
        try {
            //加锁-活动，设置5秒超时
            if (!this.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-初始化队伍-加锁-活动-超时：{}", commonTeam);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            CrossSonHaiTeam team = this.teamMap.get(commonTeam.getTeamId());
            if (team == null) {
                team = new CrossSonHaiTeam(
                        this.sonHaiConfig,
                        this.groupId,
                        commonTeam.getTeamId(),
                        commonTeam.getLeaderId()
                );
                this.teamMap.put(team.getTeamId(), team);
                //初始化区域
                int regionId = this.sonHaiConfig.getDefaultRegionId();//默认区域id
                SonHaiRegionData regionData = this.createRegion(team.getTeamId(), regionId);
                team.addRegion(regionData);
                //初始化玩家
                for (CommonTeamUserData teamUser : commonTeam.getMemberDataMap().values()) {
                    this.initUser(teamUser.getUserId(), teamUser.getServerId(), team, teamUser.getScore(), language);
                }
            }
            return team;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-初始化队伍-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            this.getLock().unlock();
        }
    }

    /**
     * 初始化玩家
     * @param userId
     * @param serverId
     * @param team
     * @return
     * @throws BusinessException
     */
    public CrossSonHaiUser initUser(long userId, long serverId, CrossSonHaiTeam team, long power, String language) throws BusinessException {
        try {
            //加锁-队伍，设置5秒超时
            if (!this.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-初始化玩家-加锁-队伍-超时：{}", userId);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            CrossSonHaiUser user = this.userMap.get(userId);
            if (user == null) {
                //体力初始值
                int energy = this.sonHaiConfig.getEnergyLimit();
                //协助次数
                int helpNum = this.sonHaiConfig.getInitHelpNum();
                //第一次圣兽降临消耗体力次数
                int nextBuffComeNeedEnergy = this.sonHaiConfig.getFistBuffComeNeedEnergy();
                //实例化玩家
                user = new CrossSonHaiUser(
                        this.sonHaiConfig,
                        this.groupId,
                        userId,
                        team.getTeamId(),
                        serverId,
                        energy,
                        nextBuffComeNeedEnergy,
                        power,
                        helpNum,
                        language
                );
                int regionId = this.sonHaiConfig.getDefaultRegionId();//默认区域id
                SonHaiRegionData regionData = team.getRegion(regionId);
                if (regionData == null) {
                    //初始化区域
                    regionData = this.createRegion(team.getTeamId(), regionId);
                    team.addRegion(regionData);
                }
                //兽王地块
                SonHaiPlotData beastKingPlot = regionData.getBeastKingPlot();
                //玩家注入队伍
                team.addMember(user);
                //玩家注入区域
                user.setRegionAndPosition(regionData, beastKingPlot.getX(), beastKingPlot.getY());
                //初始化下血量
                long allBlood = user.getPowerForPvp();
                user.setAllBlood(allBlood);
                //put map
                this.userMap.put(user.getUserId(), user);
            }
            return user;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-初始化玩家-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            this.getLock().unlock();
        }
    }

    /**
     * 创建区域
     * @param teamId 队伍ID
     * @param regionId 区域ID
     * @return
     */
    private SonHaiRegionData createRegion(int teamId, int regionId) {
        //随机出地图
        int mapId = this.sonHaiConfig.getRandomMapId(regionId);
        SonHaiMapConfig mapConfig = this.sonHaiConfig.getMapConfig(mapId);
        //实例化区域
        SonHaiRegionData regionData = new SonHaiRegionData(
                this.sonHaiConfig.getActivityInfo().getActivityId(),
                this.groupId,
                teamId,
                regionId,
                this.activityData.getMaxRegionUniqueIdAndAdd(),
                mapId
        );
        SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(regionId);
        //兽王事件
        SonHaiEventConfig eventConfig = this.sonHaiConfig.getEventConfig(floorConfig.getSpecial());
        int monsterId = eventConfig.getMonsterList().get(0);//异兽ID
        SonHaiBeastData beast = this.createBeast(monsterId, regionId);
        //随机出坐标
        List<SonHaiXYData> plotXYList = mapConfig.randomBossPosition();
        SonHaiBeastBossData boss = new SonHaiBeastBossData(eventConfig.getId(), regionData.getRegionId(), beast, plotXYList);
        regionData.setBeastBoss(boss);
        for (SonHaiXYData plotXY : plotXYList) {
            regionData.createPlot(0, plotXY.getX(), plotXY.getY(), this.sonHaiConfig.getActivityInfo().getActivityId(), this.groupId, eventConfig);
        }
        return regionData;
    }

    /**
     * 创建地块
     * @param regionData 区域
     * @param userId 玩家ID
     * @param x x
     * @param y y
     * @param autoWin 是否自动镇伏
     * @param eventId 指定事件
     * @param excludeEventIds 排除事件
     * @return
     */
    public SonHaiCreatePlotResp createPlot(SonHaiRegionData regionData, long userId, int x, int y, boolean autoWin, int eventId, Set<Integer> excludeEventIds) {
        CrossSonHaiUser user = this.getUser(userId);
        SonHaiCreatePlotResp resp = new SonHaiCreatePlotResp();
        //创建地块
        SonHaiEventConfig eventConfig;
        if (eventId > 0 && ConfigHelper.getInt("channelId") == 666) {//测试渠道才能指定事件
            eventConfig = this.pointEvent(user, regionData.getRegionId(), eventId);
        } else {
            eventConfig = this.getEventConfigByWeight(user, regionData.getRegionId(), excludeEventIds);
        }
        if (eventConfig == null) {
            return null;
        }
        SonHaiPlotData plotData = regionData.createPlot(userId, x, y, this.sonHaiConfig.getActivityInfo().getActivityId(), this.groupId, eventConfig);
        resp.setPlotData(plotData);
        resp.setOriginPlotLevel(plotData.getLevel());
        //根据不同类型的地块，处理不同的事件
        IPlotTypeHandler plotTypeHandler = this.plotTypeHandlerMap.get(plotData.getType());
        if (plotTypeHandler != null) {
            PlotTypeHandlerExploreReq req = new PlotTypeHandlerExploreReq();
            req.setActivity(this);
            req.setUser(this.getUser(userId));
            req.setPlotData(plotData);
            req.setAutoWin(autoWin);
            //执行
            PlotTypeHandlerExploreResp handlerExploreResp = plotTypeHandler.explore(req);
            if (handlerExploreResp != null) {
                if (handlerExploreResp.getNewPlotDataList() != null) {
                    resp.setExtraPlotDataList(handlerExploreResp.getNewPlotDataList());
                }
                if (handlerExploreResp.getWinPlotResp() != null) {
                    resp.setWinPlotResp(handlerExploreResp.getWinPlotResp());
                }
            }
        }
        return resp;
    }

    /**
     * 指定事件
     * @param user
     * @param reginId
     * @param eventId
     * @return
     */
    private SonHaiEventConfig pointEvent(CrossSonHaiUser user, int reginId, int eventId) {
        SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(reginId);
        SonHaiEventConfig eventConfig = this.sonHaiConfig.getEventConfig(eventId);

        //事件次数达上限
        Map<Integer, Integer> eventNumMap = floorConfig.getEventNumMap();
        SonHaiRegionData regionData = user.getRegionData();
        //已拥有的事件数量
        int num = regionData.getPlotNumByEventId(eventId);
        int eventMaxNum = eventNumMap.getOrDefault(eventId, Integer.MAX_VALUE);
        if (num >= eventMaxNum) {
            //重随
            return this.getEventConfigByWeight(user, reginId, null);
        }

        //PVP事件是否能命中
        List<UserYRank> pvpPool = this.getRandomPvpPool(user);
        if (eventConfig.getEventType() == SonHaiPlotTypeEnum.PLOT_TYPE_14.getType()) {
            if (pvpPool == null || pvpPool.isEmpty()) {
                //重随
                return this.getEventConfigByWeight(user, reginId, null);
            }
        }

        //EGG事件是否能命中
        if (eventConfig.getEventType() == SonHaiPlotTypeEnum.PLOT_TYPE_13.getType()) {
            CrossSonHaiTeam team = this.getTeam(user.getTeamId());
            Map<Integer, Set<Integer>> eggPool = this.getRandomEggPool(user, team);
            Set<Integer> eggIds = eggPool.get(eventId);
            if (eggIds == null || eggIds.isEmpty()) {
                //重随
                return this.getEventConfigByWeight(user, reginId, null);
            }
        }

        return eventConfig;
    }

    /**
     * 创建兽群
     * @return
     */
    public SonHaiBeastGroupData  createBeastGroup(List<Integer> monsterIdList) {
        int id = 0;//兽群id，有可能用不到
        Map<Integer, SonHaiBeastData> beastDataMap = new ConcurrentHashMap<>();
        for (int monsterId : monsterIdList) {
            //创建异兽
            SonHaiBeastData beast = this.createBeast(monsterId, 0);
            beastDataMap.put(monsterId, beast);
        }
        return new SonHaiBeastGroupData(id, beastDataMap);
    }

    /**
     * 创建异兽
     * @param monsterId
     * @return
     */
    public SonHaiBeastData createBeast(int monsterId, int regionId) {
        long allBlood = this.createBeastPower(monsterId, regionId);//计算怪物血量
        return new SonHaiBeastData(monsterId, allBlood);
    }

    /**
     * 计算怪物战力
     * @param monsterId
     * @return
     */
    public long createBeastPower(int monsterId, int regionId) {
        SonHaiMonsterConfig monsterConfig = this.sonHaiConfig.getMonsterConfig(monsterId);
        int vipLevel = monsterConfig.getParamList().get(0);
        int param = monsterConfig.getParamList().get(1);
        //vip战力均值 * 比例
        long avePower = this.activityData.getVipAvePowerMap().get(vipLevel);
        BigDecimal rate = BigDecimal.valueOf(param).divide(BigDecimal.valueOf(1000), 2, RoundingMode.UP);
        BigDecimal monsterPower = BigDecimal.valueOf(avePower).multiply(rate);
        //怪物战力修正
        if (regionId > 0) {
            SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(regionId);
            BigDecimal addRate = BigDecimal.valueOf(floorConfig.getMonsterHpAdd()).divide(BigDecimal.valueOf(1000), 2, RoundingMode.UP);
            return monsterPower.longValue() + monsterPower.multiply(addRate).longValue();
        } else {
            return monsterPower.longValue();
        }
    }

    /**
     * 获取PVP玩家随机池子
     * @param user
     * @return
     */
    public List<UserYRank> getRandomPvpPool(CrossSonHaiUser user) {
        List<Integer> pvpPlayerRange = this.sonHaiConfig.getPvpPlayerRange();
        int start = pvpPlayerRange.get(0);
        int end = pvpPlayerRange.get(1);
        //获取排行榜
        List<UserYRank> rankList = user.getUserSubRankList(start, end);
        if (rankList == null) {
            return null;
        }
        //玩家商会ID
        String unionId = user.getUnionId();
        //过滤
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        Set<Long> teamMemberUserIdSet = team.getMemberMap().keySet();
        Set<Long> teamPvpTargetUserIdSet = team.getPvpTargetUserIdSet();
        List<UserYRank> fiterRankList = new ArrayList<>();
        List<UserYRank> unionUserRankList = new ArrayList<>();
        for (UserYRank rank : rankList) {
            CrossSonHaiUser targetUser = this.getUser(rank.getUserId());
            if (targetUser == null) {
                continue;
            }
            //过滤被击杀次数等于0的玩家
            if (targetUser.getPvpCanBeAttNum() <= 0) {
                continue;
            }
            //过滤死亡的玩家
            if (targetUser.getDieFlag() == SonHaiDieFlagEnum.DIE_YES.getType()) {
                continue;
            }
            //过滤已经在队友地块中的玩家
            if (teamPvpTargetUserIdSet.contains(rank.getUserId())) {
                continue;
            }
            //过滤队友
            if (teamMemberUserIdSet.contains(rank.getUserId())) {
                continue;
            }
            //过滤同商会玩家
            if (unionId != null && unionId.equals(rank.getUserBaseInfo().getUnionUid())) {
                unionUserRankList.add(rank);
                continue;
            }
            fiterRankList.add(rank);
        }
        //如果都没人，用同商会玩家
        if (fiterRankList.isEmpty()) {
            return unionUserRankList;
        }
        return fiterRankList;
    }

//    /**
//     * 获取异兽蛋随机池子
//     * @param team
//     * @return k:蛋id，v:权重
//     */
//    public Map<Integer, Long> getRandomEggPool(int regionId, CrossSonHaiTeam team) {
//        Map<Integer, SonHaiEggData> eggDataMap = this.eggMap;
//        Map<Integer, Long> weightMap = new HashMap<>();
//        //队伍蛋集合
//        Set<Integer> haveEggIdSet = team.getEggIdSet();
//        //区域蛋权重配置
//        SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(regionId);
//        Map<Integer, Long> eggQualityWeightMap = floorConfig.getEggQualityWeightMap();
//        //去除队伍已有的蛋
//        for (SonHaiEggData egg : eggDataMap.values()) {
//            if (!haveEggIdSet.contains(egg.getId())) {
//                //蛋配置
//                if (eggQualityWeightMap.containsKey(egg.getEggConfigId())) {
//                    long weight = eggQualityWeightMap.get(egg.getEggConfigId());
//                    weightMap.put(egg.getId(), weight);
//                }
//            }
//        }
//        return weightMap;
//    }

    /**
     * 获取异兽蛋随机池子
     * @param team
     * @return k:蛋配置ID，v:蛋ID set
     */
    public Map<Integer, Set<Integer>> getRandomEggPool(CrossSonHaiUser user, CrossSonHaiTeam team) {
        Map<Integer, SonHaiEggData> eggDataMap = this.eggMap;
        Map<Integer, Set<Integer>> result = new HashMap<>();
        //队伍蛋集合
        Set<Integer> teamEggIdSet = team.getEggIdSet();
        //商会玩家蛋集合
        Set<Integer> unionEggIdSet = this.getUnionEggIdSet(user);
        //去除【队伍】已有的蛋,去除【商会】已有的蛋
        for (SonHaiEggData egg : eggDataMap.values()) {
            if (!teamEggIdSet.contains(egg.getId()) && !unionEggIdSet.contains(egg.getId())) {
                Set<Integer> eggIds = result.computeIfAbsent(egg.getEggConfigId(), k -> new HashSet<>());
                eggIds.add(egg.getId());
            }
        }
        return result;
    }

    /**
     * 同商会玩家持有的蛋集合
     * @param user
     * @return
     */
    public Set<Integer> getUnionEggIdSet(CrossSonHaiUser user) {
        Set<Integer> eggIdSet = new HashSet<>();
        //去除同商会占领的蛋
        Map<Long, UnionActivityGroupUser> unionUserMap = user.getUnionUserMap();
        if (unionUserMap != null) {
            for (UnionActivityGroupUser unionActivityGroupUser : unionUserMap.values()) {
                //商会玩家持有的蛋
                CrossSonHaiUser unionUser = this.getUser(unionActivityGroupUser.getUserId());
                if (unionUser != null) {
                    Map<Integer, SonHaiEggData> eggDataMap = unionUser.getUserEggDataMap();
                    if (!eggDataMap.isEmpty()) {
                        eggIdSet.addAll(eggDataMap.keySet());
                    }
                }
            }
        }
        return eggIdSet;
    }

    /**
     * 获取事件，根据权重
     * @param reginId
     * @return
     */
    private SonHaiEventConfig getEventConfigByWeight(CrossSonHaiUser user, int reginId, Set<Integer> excludeEventIds) {
        SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(reginId);
        Map<Integer, Long> eventWeightMap = new HashMap<>(floorConfig.getEventWeightMap());
        //移除掉排除事件
        if (excludeEventIds != null && !excludeEventIds.isEmpty()) {
            for (int excludeEventId : excludeEventIds) {
                eventWeightMap.remove(excludeEventId);
            }
        }

        //PVP事件是否能命中
        List<UserYRank> pvpPool = this.getRandomPvpPool(user);
        if (pvpPool == null || pvpPool.isEmpty()) {
            //移除PVP事件
            Map<Integer, SonHaiEventConfig> pvpEventMap = this.sonHaiConfig.getEventConfigMap(SonHaiPlotTypeEnum.PLOT_TYPE_14.getType());
            if (pvpEventMap != null) {
                for (SonHaiEventConfig item : pvpEventMap.values()) {
                    eventWeightMap.remove(item.getId());
                }
            }
        }

        //EGG事件是否能命中
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        Map<Integer, Set<Integer>> eggPool = this.getRandomEggPool(user, team);
        //移除EGG事件
        Map<Integer, SonHaiEventConfig> eggEventMap = this.sonHaiConfig.getEventConfigMap(SonHaiPlotTypeEnum.PLOT_TYPE_13.getType());
        if (eggEventMap != null) {
            for (SonHaiEventConfig item : eggEventMap.values()) {
                Set<Integer> eggIds = eggPool.get(item.getId());
                if (eggIds == null || eggIds.isEmpty()) {
                    eventWeightMap.remove(item.getId());
                }
            }
        }

        //移除事件次数达上限的事件
        Map<Integer, Integer> eventNumMap = floorConfig.getEventNumMap();
        SonHaiRegionData regionData = user.getRegionData();
        for (Map.Entry<Integer, Integer> entry : eventNumMap.entrySet()) {
            int eventId = entry.getKey();
            int eventMaxNum = entry.getValue();
            //已拥有的事件数量
            int num = regionData.getPlotNumByEventId(eventId);
            if (num >= eventMaxNum) {
                //达上限，移除
                eventWeightMap.remove(eventId);
            }
        }
        //权重随机事件
        int eventId = RandomHelper.getRandomKeyByLongWeight(eventWeightMap);
        SonHaiEventConfig eventConfig = this.sonHaiConfig.getEventConfig(eventId);
        if (eventConfig == null) {
            logger.error("山海伏兽-创建地块事件配置不存在：{}，{}，{}", user.getActivityId(), user.getUserId(), eventId);
        }
        return eventConfig;
    }

    /**
     * 创建地块-随机探明周边X格范围内的Y个地块
     * @param user
     * @param regionData
     * @param plotData
     * @param range X格范围内
     * @param num Y个地块
     * @param autoWin 是否自动镇伏
     * @return 新地块LIST
     */
    public List<SonHaiCreatePlotResp> randomCreatePlot(CrossSonHaiUser user, SonHaiRegionData regionData, SonHaiPlotData plotData, int range, int num, boolean autoWin) {
        //X格范围内的地块LIST
        List<Point> points = PlotUtil.getPointsInRadius(plotData.getX(), plotData.getY(), range);
        List<Point> notExplorePoints = new ArrayList<>();//未被探索的地块
        for (Point point : points) {
            //过滤不合法地块
            boolean flag = regionData.checkPlotNotAdJoin(point.getX(), point.getY(), this.sonHaiConfig);
            //是否被封锁
            boolean lockFlag = regionData.checkPlotLock(point.getX(), point.getY(), this.sonHaiConfig);
            if (flag && !lockFlag) {
                notExplorePoints.add(point);
            }
        }
        //随机出Y个地块
        List<Point> targetPoints = ListHelper.getRandomSubList(notExplorePoints, num);

        //探明区域
        List<SonHaiCreatePlotResp> newPlotDataList = new ArrayList<>();
        for (Point point : targetPoints) {
            //过滤不合法地块
            boolean flag = regionData.checkPlotNotAdJoin(point.getX(), point.getY(), this.sonHaiConfig);
            if (flag) {
                //创建地块，排除封锁事件
                Map<Integer, SonHaiEventConfig> eventMap = this.sonHaiConfig.getEventConfigMap(SonHaiPlotTypeEnum.PLOT_TYPE_6.getType());
                SonHaiCreatePlotResp createPlotResp = this.createPlot(regionData, user.getUserId(), point.getX(), point.getY(), autoWin, 0, eventMap.keySet());
                if (createPlotResp != null) {
                    newPlotDataList.add(createPlotResp);
                }
            }
        }
        return newPlotDataList;
    }

    /**
     * check打自己的-boss
     * @param user
     * @param bossData
     * @return
     * @throws BusinessException
     */
    private int checkAttackedSelfForBoss(CrossSonHaiUser user, SonHaiBeastBossData bossData) throws BusinessException {
        //打过BOSS的次数
        int attNum = bossData.getAttNum(user.getUserId());
        //体力消耗配置
        List<Integer> energyCostList = this.sonHaiConfig.getEnergySpecialPveCost();
        //体力倍数
        SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(bossData.getRegionId());
        return this.checkAttackedSelf(user, attNum, energyCostList, floorConfig.getEnergy());
    }

    /**
     * check打自己的-地块
     * @param user
     * @param plotData
     * @return
     * @throws BusinessException
     */
    private int checkAttackedSelfForPlot(CrossSonHaiUser user, SonHaiPlotData plotData) throws BusinessException {
        //打过该地块的次数
        int attNum = plotData.getAttNum(user.getUserId());
        //体力消耗配置
        List<Integer> energyCostList = this.sonHaiConfig.getEnergyFinderCost();
        //体力倍数
        SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(plotData.getRegionId());
        return this.checkAttackedSelf(user, attNum, energyCostList, floorConfig.getEnergy());
    }

    /**
     * check打自己的
     * @param user
     * @param attNum
     * @return
     * @throws BusinessException
     */
    private int checkAttackedSelf(CrossSonHaiUser user, int attNum, List<Integer> energyCostList, int baseEnergy) throws BusinessException {
        if (attNum <= 0) {
            //第一次攻击，不消耗体力
            return 0;
        }
        //体力公式 = min（初始值 + 已被攻击次数×递增值，最大值）×体力倍数
        int initValue = 1;
        int addValue = energyCostList.get(0);
        int maxValue = energyCostList.get(1);
        int energyMul = Math.min(initValue + attNum * addValue, maxValue);
        //消耗体力
        int energyCost = 0;
        if (energyMul > 0) {
            energyCost = energyMul * baseEnergy;
            boolean consumeEnergyFlag = user.reduceEnergy(energyCost);
            if (!consumeEnergyFlag) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_ENERGY_NOT_ENOUGH);
            }
        }
        return energyCost;
    }

//    /**
//     * check打队友的（协助）
//     * @param user
//     * @param plotData
//     * @throws BusinessException
//     */
//    private int checkAttackedTeamMember(CrossSonHaiUser user, SonHaiPlotData plotData) throws BusinessException {
//        //打过该地块的次数
//        int attNum = plotData.getAttNum(user.getUserId());
//        //消耗体力值
//        List<Integer> energyCostList = this.sonHaiConfig.getEnergyHelperCost();
////        if (attNum <= 0) {
////            //第一次攻击，消耗协助次数
////            boolean consumeHelpNumFlag = user.consumeHelpNum(1);
////            if (consumeHelpNumFlag) {
////                return 0;
////            }
////        }
//        //体力公式 = min（初始值 + 已被攻击次数×递增值，最大值）×体力倍数
//        int initValue = 1;
//        int addValue = energyCostList.get(0);
//        int maxValue = energyCostList.get(1);
//        int energyMul = Math.min(initValue + attNum * addValue, maxValue);
//        //消耗体力
//        SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(plotData.getRegionId());
//        int energyCost = energyMul * floorConfig.getEnergy();
//        boolean consumeEnergyFlag = user.reduceEnergy(energyCost);
//        if (!consumeEnergyFlag) {
//            throw BusinessException.newException(GameErrorCode.E_SON_HAI_ENERGY_NOT_ENOUGH);
//        }
//        return energyCost;
//    }

    /**
     * check打队友的（协助）-pve
     * @param user
     * @param beastData
     * @return
     * @throws BusinessException
     */
    private int checkAttackedTeamMemberForPve(CrossSonHaiUser user, SonHaiBeastData beastData) throws BusinessException {
        //判断是否协助cd
        if (beastData.checkHelpCd(user.getUserId(), this.sonHaiConfig.getHelpCd())) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_HELP_CD);
        }
        //打队友的，消耗协助次数
        boolean consumeHelpNumFlag = user.consumeHelpNum(1);
        if (!consumeHelpNumFlag) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_BATTLE_HELP_NUM_NOT_ENOUGH);
        }
        return 0;
    }

    /**
     * check打队友的（协助）-egg
     * @param user
     * @param eggData
     * @return
     * @throws BusinessException
     */
    private int checkAttackedTeamMemberForEgg(CrossSonHaiUser user, SonHaiEggData eggData) throws BusinessException {
        //判断是否协助cd
        if (eggData.checkHelpCd(user.getUserId(), this.sonHaiConfig.getHelpCd())) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_HELP_CD);
        }
        //打队友的，消耗协助次数
        boolean consumeHelpNumFlag = user.consumeHelpNum(1);
        if (!consumeHelpNumFlag) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_BATTLE_HELP_NUM_NOT_ENOUGH);
        }
        return 0;
    }

    /**
     * check打队友的（协助）-pvp
     * @param user
     * @param targetUser
     * @return
     * @throws BusinessException
     */
    private int checkAttackedTeamMemberForPvp(CrossSonHaiUser user, CrossSonHaiUser targetUser) throws BusinessException {
        //判断是否协助cd
        if (targetUser.checkHelpCd(user.getUserId())) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_HELP_CD);
        }
        //打队友的，消耗协助次数
        boolean consumeHelpNumFlag = user.consumeHelpNum(1);
        if (!consumeHelpNumFlag) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_BATTLE_HELP_NUM_NOT_ENOUGH);
        }
        return 0;
    }


    /**
     * 同步在该区域的其他队友，刷一下区域
     * @param pushUserId 推送的队友ID
     */
    private void pushRegionResetMsg(long pushUserId, long launchRestUserId) {
        //玩家信息
        CrossUserBaseInfo userBaseInfo = CrossUserMgr.getCrossUserBaseInfo(pushUserId);
        if (userBaseInfo != null) {
            SonHaiProto.SonHaiPushResetRegionMsg.Builder pushMsg = SonHaiProto.SonHaiPushResetRegionMsg.newBuilder();
            pushMsg.setMemberUserId(launchRestUserId);
            MessageHelper.sendPacket(userBaseInfo.getUserBaseInfo().getServerId(), userBaseInfo.getUserId(), YanQuMessageUtils.buildMessage(Protocol.U_SON_HAI_PUSH_REGION_RESET_MSG, pushMsg));
        }
    }

    /**
     * 通用检查
     * @param checkInTime
     * @param checkInDailyBattleTime
     * @throws BusinessException
     */
    public void commonCheck(boolean checkInTime, boolean checkInDailyBattleTime) throws BusinessException {
        //判断活动是否在展示期
        if (!ActivityMgr.activityInShowTime(this.sonHaiConfig.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_ACTIVITY_NOT_IN_SHOW_TIME);
        }
        //判断活动是否在活动期
        if (checkInTime && !ActivityMgr.activityInTime(this.sonHaiConfig.getActivityInfo())) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_ACTIVITY_NOT_IN_TIME);
        }
        //判断是否在每天活动进行期
        if (checkInDailyBattleTime && !this.sonHaiConfig.checkInDailyBattleTime()) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_ACTIVITY_NOT_IN_DAILY_BATTLE_TIME);
        }
        //判断是否不在组队期
        CommonTeamMgr.checkNotInTeamTime(this.sonHaiConfig.getActivityInfo().getActivityId(), this.groupId);
        //判断战力数据是否生成完毕
        if (this.activityData.getVipAvePowerMap().isEmpty()) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_POWER_DATA_NOT_CREATE);
        }
    }

    /**
     * 同步探索地块变更
     * @param user
     * @param createPlotResp
     */
    public void syncExplorePlotChange(CrossSonHaiUser user, SonHaiCreatePlotResp createPlotResp) {
        this.syncPlotChange(user, null, createPlotResp);
    }

    /**
     * 同步普通地块变更
     * @param user
     * @param plotDataList
     */
    public void syncNormalPlotChange(CrossSonHaiUser user,  List<SonHaiPlotData> plotDataList) {
        this.syncPlotChange(user, plotDataList, null);
    }

    /**
     * 同步普通地块变更
     * @param user
     * @param plotData
     */
    private void syncNormalPlotChange(CrossSonHaiUser user, SonHaiPlotData plotData) {
        List<SonHaiPlotData> plotDataList = new ArrayList<>();
        plotDataList.add(plotData);
        this.syncNormalPlotChange(user, plotDataList);
    }

    /**
     * 同步变更的地块
     * @param user
     * @param plotDataList
     */
    private void syncPlotChange(CrossSonHaiUser user, List<SonHaiPlotData> plotDataList, SonHaiCreatePlotResp createPlotResp) {
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        //变更的地块
        SonHaiProto.SonHaiSyncRegionPlotChangeMsg.Builder syncMsg = SonHaiProto.SonHaiSyncRegionPlotChangeMsg.newBuilder();
        SonHaiRegionData regionData = null;
        if (plotDataList != null) {
            for (SonHaiPlotData plot : plotDataList) {
                syncMsg.addPlots(SonHaiActivityPb.buildSonHaiSimplePlotData(plot));
            }
            if (!plotDataList.isEmpty()) {
                regionData = team.getRegion(plotDataList.get(0).getRegionId());
            }
        }
        if (regionData == null) {
            regionData = user.getRegionData();
        }
        if (createPlotResp != null) {
            SonHaiProto.SonHaiExploreResult.Builder exploreResult = SonHaiActivityPb.buildSonHaiExploreResult(createPlotResp);
            syncMsg.setExploreResult(exploreResult);
        }
        syncMsg.setProgress(regionData.getProgress());
        syncMsg.setBoss(SonHaiActivityPb.builderSonHaiBeastBossData(regionData.getBeastBoss()));
        //同步给同一个区域的队友
        for (CrossSonHaiUser member : team.getMemberMap().values()) {
            if (member.getRegionId() == regionData.getRegionId() && member.getUserId() != user.getUserId()) {
                //同步
                MessageHelper.sendPacket(member.getServerId(), member.getUserId(), YanQuMessageUtils.buildMessage(Protocol.U_SON_HAI_SYNC_REGION_PLOT_CHANGE_MSG, syncMsg));
            }
        }
    }

    /**
     * 添加战斗日志
     * @param eventId
     * @param userId
     * @param targetUserId
     * @param type
     * @param eggData
     * @param reward
     * @param loseAuraScore
     */
    public void addBattleLog(int eventId, long userId, long targetUserId, int type, SonHaiEggData eggData, String reward, long score, long addAuraScore, long loseAuraScore) {
        SonHaiBattleLog battleLog = new SonHaiBattleLog();
        battleLog.setType(type);
        battleLog.setEventId(eventId);
        battleLog.setUserId(userId);
        battleLog.setTargetUserId(targetUserId);
        if (eggData != null) {
            battleLog.setEggId(eggData.getId());
            battleLog.setEggConfigId(eggData.getEggConfigId());
            battleLog.setEggName(eggData.getEggName());
        }
        battleLog.setReward(reward);
        battleLog.setLoseAuraScore(loseAuraScore);
        battleLog.setScore(score);
        battleLog.setAuraScore(addAuraScore);
        //活动日志
        this.battleLogList.add(battleLog);
        //个人日志
        CrossSonHaiUser user = this.getUser(userId);
        if (user != null) {
            user.addBattleLog(battleLog);
        }
        //pvp和egg日志，被打的人也需要记录日志
        if (type == SonHaiBattleLogTypeEnum.PVP.getType() || type == SonHaiBattleLogTypeEnum.EGG.getType()) {
            if (targetUserId > 0) {
                CrossSonHaiUser targetUser = this.getUser(targetUserId);
                if (targetUser != null) {
                    targetUser.addBattleLog(battleLog);
                }
            }
        }
    }

    /**
     * DEBUG
     * @param userId
     * @param code
     * @param param
     * @throws BusinessException
     */
    public void debug(long userId, String code, String param) throws BusinessException {
        if (ConfigHelper.getInt("channelId") != 666) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_ACTIVITY_NOT_FOUND);
        }
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取玩家区域
        if (user.getRegionData() == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
        }
        //指定事件探索
        if (code.equals("/sonHaiExplore")) {
            // /sonHaiExplore x,y,事件id     例子：/sonHaiExplore 5,5,20002
            String[] split = param.split(",");
            int x = Integer.parseInt(split[0]);
            int y = Integer.parseInt(split[1]);
            int eventId = Integer.parseInt(split[2]);
            this.explore(userId, x, y, eventId);
        }
        //修改营地指定pvp玩家
        if (code.equals("/sonHaiPointPvpUserId")) {
            // /sonHaiPointPvpUserId x,y,玩家ID     例子：/sonHaiPointPvpUserId 5,5,1000012458578
            String[] split = param.split(",");
            int x = Integer.parseInt(split[0]);
            int y = Integer.parseInt(split[1]);
            long pvpUserId = Long.parseLong(split[2]);
            SonHaiPlotData plotData = user.getRegionData().getPlotDataMap().get(x + "_" + y);
            if (plotData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_NOT_FOUND);
            }
            if (plotData.getType() != SonHaiPlotTypeEnum.PLOT_TYPE_14.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_TYPE_ERROR);
            }
            CrossSonHaiUser pvpUser = this.userMap.get(pvpUserId);
            if (pvpUser == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
            }
            //获取队伍
            CrossSonHaiTeam team = this.getTeam(user.getTeamId());
            if (team == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
            }
            Set<Long> pvpTargetUserIdSet = team.getPvpTargetUserIdSet();
            if (pvpTargetUserIdSet.contains(pvpUserId)) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_TARGET_USER_ALREADY_INT_TEAM);
            }
            plotData.setPvpUserId(pvpUserId);
            return;
        }
        //修改异兽栖息地指定蛋ID
        if (code.equals("/sonHaiPointEggId")) {
            // /sonHaiPointEggId x,y,蛋ID    例子：/sonHaiPointEggId 6,12,68
            String[] split = param.split(",");
            int x = Integer.parseInt(split[0]);
            int y = Integer.parseInt(split[1]);
            int eggId = Integer.parseInt(split[2]);
            SonHaiPlotData plotData = user.getRegionData().getPlotDataMap().get(x + "_" + y);
            if (plotData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_NOT_FOUND);
            }
            if (plotData.getWinFlag() == SonHaiWinFlagEnum.WIN_YES.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_ALREADY_WIN);
            }
            if (plotData.getType() != SonHaiPlotTypeEnum.PLOT_TYPE_13.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_TYPE_ERROR);
            }
            //旧蛋
            SonHaiEggData oldEggData = this.eggMap.get(plotData.getEggId());
            if (oldEggData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EGG_NOT_FOUND);
            }
            //新蛋
            SonHaiEggData eggData = this.eggMap.get(eggId);
            if (eggData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EGG_NOT_FOUND);
            }
            SonHaiEggConfig eggConfig = this.sonHaiConfig.getEggConfig(eggData.getEggConfigId());
            if (eggConfig == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EGG_NOT_FOUND);
            }
            //获取队伍
            CrossSonHaiTeam team = this.getTeam(user.getTeamId());
            if (team == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
            }
            Set<Integer> eggIdSet = team.getEggIdSet();
            if (eggIdSet.contains(eggId)) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EGG_ALREADY_INT_TEAM);
            }
            plotData.setEggId(eggId);
            plotData.setPlotId(eggConfig.getId());
            plotData.setLevel(eggConfig.getLevel());
            //旧蛋移除地块
            oldEggData.removeAttackMeUserPlot(plotData.getUserId());
            //新蛋蛋注入地块
            eggData.addAttackMeUserPlot(plotData);
            logger.info("山海伏兽-debug-修改eggId，{}", eggId);
            return;
        }
        //赋予buff
        if (code.equals("/sonHaiPointBuff")) {
            // /sonHaiPointBuff BUFFID,等级     例子：/sonHaiPointBuff 60001,1
            String[] split = param.split(",");
            int buffId = Integer.parseInt(split[0]);
            int level = Integer.parseInt(split[1]);
            SonHaiBuffConfig buffConfig = this.sonHaiConfig.getBuffConfig(buffId);
            if (buffConfig == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_BUFF_NOT_FOUND);
            }
            SonHaiBuffData buffData = user.getBuffMap().get(buffId);
            if (buffData == null) {
                buffData = new SonHaiBuffData();
                buffData.setBuffId(buffId);
                buffData.setLevel(0);
                user.addBuff(buffData);
            }
            buffData.setLevel(level);

            return;
        }
        //叫寻踪进度
        if (code.equals("/sonHaiAddProgress")) {
            // /sonHaiAddProgress 值     例子：/sonHaiAddProgress 100000
            String[] split = param.split(",");
            int value = Integer.parseInt(split[0]);
            SonHaiRegionData regionData = user.getRegionData();
            regionData.setProgress(regionData.getProgress() + value);
        }
        //加积分
        if (code.equals("/sonHaiAddScore")) {
            // /sonHaiAddScore 值     例子：/sonHaiAddScore 100000
            String[] split = param.split(",");
            int value = Integer.parseInt(split[0]);
            user.addScore(value);
        }
        //修改玩家区域
        if (code.equals("/sonHaiChangeRegion")) {
            // /sonHaiChangeRegion 区域ID      例子：/sonHaiChangeRegion 10004
            String[] split = param.split(",");
            int regionId = Integer.parseInt(split[0]);
            CrossSonHaiTeam team = this.getTeam(user.getTeamId());
            //判断区域ID是否合法,是否在配置区域里
            SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(regionId);
            if (floorConfig == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
            }
            if (team == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
            }
            //获取区域
            SonHaiRegionData oldRegionData = user.getRegionData();
            if (oldRegionData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
            }
            if (regionId > team.getMaxRegionId()) {
                team.setMaxRegionId(regionId);
            }
            //获取区域
            SonHaiRegionData regionData = team.getRegion(regionId);
            //判断区域是否存在
            if (regionData == null) {
                //区域不存在，创建区域
                regionData = this.createRegion(team.getTeamId(), regionId);
                //set新区域
                team.addRegion(regionData);
            }

            //判断玩家当前区域是否还有队伍成员，如果没有，需要删除区域
            boolean delFlag = true;
            for (CrossSonHaiUser member : team.getMemberMap().values()) {
                if (member.getUserId() != userId && member.getRegionId() == oldRegionData.getRegionId()) {
                    delFlag = false;
                }
            }
            if (delFlag) {
                //移除区域
                team.removeRegion(oldRegionData.getRegionId());
            }
            //玩家注入区域
            SonHaiPlotData beastBossPlot = regionData.getBeastKingPlot();
            user.setRegionAndPosition(regionData, beastBossPlot.getX(), beastBossPlot.getY());
            return;
        }
    }

    /**
     * 战力转换
     * @param patronsDataMap
     */
    private void transformPatronsPower(Map<Integer, SonHaiPatronsData> patronsDataMap) {
        for (SonHaiPatronsData patronsData : patronsDataMap.values()) {
            long power = this.sonHaiConfig.transformPatronsPower(patronsData.getAbility());
            patronsData.setAbility(power);
            //顺便初始化下血量
            if (patronsData.getAllBlood() == 0) {
                patronsData.setAllBlood(power);
            }
        }
    }

    /**
     * 同步玩家数据
     * @param userId
     */
    public void syncUserData(long userId, boolean syncRedDot) {
        CrossSonHaiUser user = this.getUser(userId);
        if (user != null && user.getRegionData() != null) {
            user.syncUserData(syncRedDot);
        }
    }

    /**
     * 同步玩家所有红点
     * @param userId
     */
    public void syncUserAllRedDot(long userId) {
        //同步红点
        CrossSonHaiUser user = this.getUser(userId);
        if (user != null) {
            user.syncAllRedDotMsg();
        }
    }

    /**
     * 添加探索日志
     * @param user
     * @param createPlotResp
     * @param regionData
     */
    private void addExploreLog(CrossSonHaiUser user, SonHaiCreatePlotResp createPlotResp, SonHaiRegionData regionData) {
        SonHaiPlotData plotData = createPlotResp.getPlotData();
        SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(plotData.getRegionId());
        //获取奖励，积分，寻踪进度
        String reward = "";
        long score = 0;
        int progress = 0;
        if (createPlotResp.getWinPlotResp() != null) {
            reward = createPlotResp.getWinPlotResp().getReward();
            score = createPlotResp.getWinPlotResp().getAddScore();
            progress = createPlotResp.getWinPlotResp().getAddProgress();
        }
        LogCrossSonHaiExplore log = new LogCrossSonHaiExplore(
                this.activityData.getActivityId(),
                this.groupId,
                user.getUserId(),
                user.getTeamId(),
                plotData.getRegionId(),
                plotData.getY() + "," + plotData.getY(),
                floorConfig.getEnergy(),
                user.getEnergy(),
                plotData.getPlotId(),
                reward,
                score,
                progress,
                regionData.getProgress()
        );
        CrossAutoLogMgr.add(log);
    }

    /**
     * 添加战斗日志-旧战斗结果
     * @param user
     * @param plotData
     * @param resp
     * @param costEnergy
     * @param regionData
     */
    public void addFightLog(CrossSonHaiUser user, SonHaiPlotData plotData, SonHaiBattleResp resp, int costEnergy, SonHaiRegionData regionData) {
        SonHaiNewBattleResp newResp = new SonHaiNewBattleResp();
        newResp.setWinFlag(resp.isWinFlag());
        long damage = 0;
        for (SonHaiBattleOneResp oneResp : resp.getBattleList()) {
            damage += oneResp.getDamage();
        }
        newResp.setDamage(damage);
        newResp.setReward(resp.getReward());
        newResp.setAddScore(resp.getAddScore());
        newResp.setAddProgress(resp.getAddProgress());
        newResp.setAddAuraScore(resp.getAddAuraScore());
        this.addFightLog(user, plotData, newResp, costEnergy, regionData);
    }

    /**
     * 添加战斗日志-新战斗结果
     * @param user
     * @param plotData
     * @param resp
     * @param costEnergy
     * @param regionData
     */
    public void addFightLog(CrossSonHaiUser user, SonHaiPlotData plotData, SonHaiNewBattleResp resp, int costEnergy, SonHaiRegionData regionData) {
        long targetId = 0;
        if (plotData.getPvpUserId() > 0) {
            targetId = plotData.getPvpUserId();
        }
        if (plotData.getEggId() > 0) {
            targetId = plotData.getEggId();
        }
        long harm = resp.getDamage();
        LogCrossSonHaiBattle log = new LogCrossSonHaiBattle(
                this.activityData.getActivityId(),
                this.groupId,
                user.getUserId(),
                user.getTeamId(),
                plotData.getRegionId(),
                plotData.getPlotId(),
                plotData.getUserId(),
                targetId,
                costEnergy,
                user.getEnergy(),
                resp.isWinFlag() ? 1 : 0,
                harm,
                resp.getReward(),
                resp.getAddScore(),
                resp.getAddProgress(),
                regionData.getProgress(),
                resp.getAddAuraScore()
        );
        CrossAutoLogMgr.add(log);
    }

    /**************************************交互方法********************************************/

    /**
     * 进入活动
     * @param userId
     * @param serverId
     * @throws BusinessException
     */
    public void enterActivity(long userId, long serverId, long power, int talentAddition, String language) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取下通用队伍信息
        CommonTeam commonTeam = CommonTeamMgr.getTeamByUserId(sonHaiConfig.getActivityInfo().getActivityId(), this.groupId, userId);
        //获取队伍，不存在则初始化
        CrossSonHaiTeam team = this.getTeam(commonTeam.getTeamId());
        if (team == null) {
            this.initTeam(commonTeam, language);
        }
        //获取下玩家
        CrossSonHaiUser user = this.getUser(userId);
        //玩家战力，天赋技能战力加成。每次进入活动更新
        user.setPower(power);
        user.setTalentAddition(talentAddition);

        //初始化下血量
        if (user.getAllBlood() <= 0) {
            long allBlood = user.getPowerForPvp();
            user.setAllBlood(allBlood);
        }

        //自动恢复体力
        user.energyRestore();

        //更新下语言
        user.setLanguage(language);

        //推送一下战力的蛋被抢信息
        user.pushLostEggMsg();

        //同步红点
        user.syncAllRedDotMsg();
    }

    /**
     * 探索
     * @param userId
     * @param x
     * @param y
     * @return
     * @throws BusinessException
     */
    public SonHaiCreatePlotResp explore(long userId, int x, int y, int eventId) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-探索-加锁-队伍-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //判断玩家是否死亡
            if (user.getDieFlag() == SonHaiDieFlagEnum.DIE_YES.getType()) {
                this.syncUserData(userId, false);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_DIE);
            }
            //获取玩家区域
            SonHaiRegionData regionData = user.getRegionData();
            if (regionData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
            }
            //检查探索的地块是否合法
            boolean checkPlotFlag = regionData.checkPlot(x, y, this.sonHaiConfig);
            if (!checkPlotFlag) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_POINT_ERROR);
            }
            //判断地块是否被封锁
            boolean lockFlag = regionData.checkPlotLock(x, y, this.sonHaiConfig);
            if (lockFlag) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_LOCK);
            }
            //判断体力是否足够
            boolean consumeEnergyFlag = user.checkExploreEnergyEnough();
            if (!consumeEnergyFlag) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_ENERGY_NOT_ENOUGH);
            }
            //玩家坐标变更
            user.setPosition(x, y);
            //创建地块
            SonHaiCreatePlotResp createPlotResp = this.createPlot(regionData, userId, x, y, false, eventId, null);
            if (createPlotResp == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EVENT_NOT_EXIST);
            }
            //消耗体力
            user.exploreReduceEnergy();
            if (createPlotResp.getWinPlotResp() != null) {
                //同步队友游戏服队伍积分变更
                team.syncTeamUserScore();
            }
            //同步同一个区域里的队友，同步探索地块变更
            this.syncExplorePlotChange(user, createPlotResp);
            //添加探索日志
            this.addExploreLog(user, createPlotResp, regionData);
            //返回
            return createPlotResp;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-探索-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * 获取地块详情
     * @param userId
     * @param regionId
     * @param x
     * @param y
     * @return
     * @throws BusinessException
     */
    public SonHaiGetPlotDetailResp getPlotDetail(long userId, int regionId, int x, int y) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        //获取玩家区域
        if (user.getRegionData() == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
        }
        //获取区域
        SonHaiRegionData regionData;
        if (regionId == 0) {
            regionData = user.getRegionData();
        } else {
            regionData = team.getRegion(regionId);
        }
        if (regionData == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
        }
        //获取地块详情
        SonHaiPlotData plotData = regionData.getPlotData(x, y);
        if (plotData == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_NOT_FOUND);
        }
        //判断地块是否被封锁
        boolean lockFlag = regionData.checkPlotLock(plotData.getX(), plotData.getY(), this.sonHaiConfig);
        if (lockFlag) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_LOCK);
        }
        SonHaiGetPlotDetailResp resp = new SonHaiGetPlotDetailResp();
        resp.setRegionData(regionData);
        resp.setPlotData(plotData);
        boolean pveFlag = true;//pve 或者是 pvp
        long helpCdEndTime = 0;//协助CD结束时间
        //异兽
        if (plotData.getBeastData() != null) {
            if (userId != plotData.getUserId()) {
                helpCdEndTime = plotData.getBeastData().getHelpCdEndTime(userId, this.sonHaiConfig.getHelpCd());
            }
        }
        //兽王
        if (plotData.getType() == SonHaiPlotTypeEnum.PLOT_TYPE_1.getType()) {
            resp.setBeastBossData(regionData.getBeastBoss());
        }
        //PVP玩家数据
        if (plotData.getPvpUserId() > 0) {
            CrossSonHaiUser pvpUser = this.userMap.get(plotData.getPvpUserId());
            if (pvpUser == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_TARGET_USER_NOT_FOUND);
            }
            resp.setUserData(pvpUser);
            pveFlag = false;
            if (userId != plotData.getUserId()) {
                helpCdEndTime = pvpUser.getHelpCdEndTime(userId);
            }
        }
        //兽蛋数据
        if (plotData.getEggId() > 0) {
            SonHaiEggData eggData = this.eggMap.get(plotData.getEggId());
            if (eggData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EGG_NOT_FOUND);
            }
            resp.setEggData(eggData);
            if (eggData.getUserId() > 0) {
                pveFlag = false;
            }
            if (userId != plotData.getUserId()) {
                helpCdEndTime = eggData.getHelpCdEndTime(userId, this.sonHaiConfig.getHelpCd());
            }
        }
        resp.setHelpCdEndTime(helpCdEndTime);

        //获取一下门战力加成
        resp.setPowerAddRateForNormal(user.getPowerAddRateForAll());//通用加成
        int powerAddRate;//总加成
        if (pveFlag) {
            powerAddRate = user.getPowerAddRateForPve(regionData);
            resp.setPowerAddRateFroOnlyPve(user.getPowerAddRateForOnlyPve(regionData));//pve单独加成
        } else {
            powerAddRate = user.getPowerAddRateForPvp();
        }
        resp.setPowerAddRate(powerAddRate);

        //异兽战力提升地块
        if (pveFlag) {
            List<SonHaiPlotBuffResp> beastPowerAddPlots = regionData.getPlotBeatsBattlePowerAddRateDetail(x, y, this.sonHaiConfig);
            resp.setBeastPowerAddPlots(beastPowerAddPlots);
        }
        //积分减益地块
        List<SonHaiPlotBuffResp> scoreRePlots = regionData.getPlotScoreReduceRateDetail(x, y, this.sonHaiConfig);
        resp.setScoreRePlots(scoreRePlots);
        //寻踪进度减益地块
        List<SonHaiPlotBuffResp> progressRePlots = regionData.getPlotProgressReduceValueDetail(x, y, this.sonHaiConfig);
        resp.setProgressRePlots(progressRePlots);

        return resp;
    }

    /**
     * 获取驻守蛋的门客map
     * @param userId
     * @return
     * @throws BusinessException
     */
    public Map<Integer, SonHaiPatronsEgg> getInEggPatronsMap(long userId) throws BusinessException {
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //遍历一下蛋
        Map<Integer, SonHaiPatronsEgg> map = new HashMap<>();
        Map<Integer, SonHaiEggData> userEggMap = user.getUserEggDataMap();
        for (SonHaiEggData eggData : userEggMap.values()) {
            for (SonHaiPatronsData patronsData : eggData.getPatronsDataMap().values()) {
                SonHaiPatronsEgg patronsEgg = new SonHaiPatronsEgg();
                patronsEgg.setPatronsId(patronsData.getPatronsId());
                patronsEgg.setEggData(eggData);
                map.put(patronsData.getPatronsId(), patronsEgg);
            }
        }
        return map;
    }

    /**
     * pve战斗
     * @param userId
     * @param regionId
     * @param x
     * @param y
     * @return
     * @throws BusinessException
     */
    public SonHaiNewBattleResp pveBattle(long userId, int regionId, int x, int y) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-pve战斗-加锁-队伍-超时：{}, {}, {}, {}", userId, regionId, x, y);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //获取玩家区域
            if (user.getRegionData() == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
            }
            //判断玩家是否死亡
            if (user.getDieFlag() == SonHaiDieFlagEnum.DIE_YES.getType()) {
                this.syncUserData(userId, false);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_DIE);
            }
            //获取区域
            SonHaiRegionData regionData = team.getRegion(regionId);
            if (regionData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
            }
            //获取地块
            SonHaiPlotData plotData = regionData.getPlotData(x, y);
            if (plotData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_NOT_FOUND);
            }
            //判断地块是否被镇伏
            if (plotData.getWinFlag() == SonHaiWinFlagEnum.WIN_YES.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_ALREADY_WIN);
            }
            //判断地块是否被封锁
            boolean lockFlag = regionData.checkPlotLock(plotData.getX(), plotData.getY(), this.sonHaiConfig);
            if (lockFlag) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_LOCK);
            }
            //判断地块兽是否存在
            if (plotData.getBeastData() == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_BEAST_GROUP_NOT_FOUND);
            }
            //事件配置
            SonHaiEventConfig eventConfig = this.sonHaiConfig.getEventConfig(plotData.getPlotId());
            if (eventConfig == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EVENT_NOT_EXIST);
            }
            //是打自己的还是打队友的
            int costEnergy = 0;
            if (plotData.getUserId() == userId) {
                //打自己的
                costEnergy = this.checkAttackedSelfForPlot(user, plotData);
            } else {
                //协助队友的
                costEnergy = this.checkAttackedTeamMemberForPve(user, plotData.getBeastData());
            }
            //战斗
            SonHaiNewBattleResp resp = user.doPveBattle(regionData, plotData);
            //日志
            if (resp.isWinFlag() && eventConfig.getLevel() >= this.sonHaiConfig.getLogPveLevel()) {
                this.addBattleLog(
                        plotData.getPlotId(),
                        plotData.getUserId(),
                        0,
                        SonHaiBattleLogTypeEnum.PVE.getType(),
                        null,
                        resp.getReward(),
                        resp.getAddScore(),
                        resp.getAddAuraScore(),
                        0);
            }
            //增加山海灵气
            if (resp.getAddAuraScore() > 0) {
                team.changeAuraScore(user, resp.getAddAuraScore());
            }
            //同步队友游戏服队伍积分变更
            team.syncTeamUserScore();
            //同步地块变更
            this.syncNormalPlotChange(user, plotData);
            //战斗日志
            this.addFightLog(user, plotData, resp, costEnergy, regionData);
            //同步队友用奖励可领取红点
            if (resp.isWinFlag() && plotData.getUserId() != userId) {
                CrossSonHaiUser teamUser = this.getUser(plotData.getUserId());
                if (teamUser != null) {
                    teamUser.syncRedDotMsg(SonHaiRedDotTypeEnum.TYPE_NULL, SonHaiRedDotTypeEnum.TYPE_HAVE, SonHaiRedDotTypeEnum.TYPE_NULL);
                }
            }
            return resp;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-PVE战斗-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * pvp战斗
     * @param userId
     * @param regionId
     * @param x
     * @param y
     * @return
     * @throws BusinessException
     */
    public SonHaiNewBattleResp pvpBattle(long userId, int regionId, int x, int y) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        try {
            //加锁-活动，设置5秒超时
            if (!this.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-pvp战斗-加锁-活动-超时：{}, {}, {}, {}", userId, regionId, x, y);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //获取玩家
            CrossSonHaiUser user = this.getUser(userId);
            if (user == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
            }
            //获取玩家区域
            if (user.getRegionData() == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
            }
            //判断玩家是否死亡
            if (user.getDieFlag() == SonHaiDieFlagEnum.DIE_YES.getType()) {
                this.syncUserData(userId, false);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_DIE);
            }
            //获取队伍
            CrossSonHaiTeam team = this.getTeam(user.getTeamId());
            if (team == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
            }
            //获取区域
            SonHaiRegionData regionData = team.getRegion(regionId);
            if (regionData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
            }
            //获取地块
            SonHaiPlotData plotData = regionData.getPlotData(x, y);
            if (plotData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_NOT_FOUND);
            }
            //判断地块是否被镇伏
            if (plotData.getWinFlag() == SonHaiWinFlagEnum.WIN_YES.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_ALREADY_WIN);
            }
            //判断地块是否被封锁
            boolean lockFlag = regionData.checkPlotLock(plotData.getX(), plotData.getY(), this.sonHaiConfig);
            if (lockFlag) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_LOCK);
            }
            //判断对方玩家是否存在
            if (plotData.getPvpUserId() <= 0) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_TARGET_USER_NOT_FOUND);
            }
            //判断对方玩家是否存在
            CrossSonHaiUser targetUser = this.getUser(plotData.getPvpUserId());
            if (targetUser == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_TARGET_USER_NOT_FOUND);
            }
            //是打自己的还是打队友的
            int costEnergy;
            if (plotData.getUserId() == userId) {
                //打自己的
                costEnergy = this.checkAttackedSelfForPlot(user, plotData);
            } else {
                //协助队友的
                costEnergy = this.checkAttackedTeamMemberForPvp(user, targetUser);
            }
            //战斗
            SonHaiNewBattleResp resp = user.doPvpBattle(regionData, plotData, targetUser);
            //PVP战斗日志
            if (resp.isWinFlag()) {
                this.addBattleLog(plotData.getPlotId(), userId, targetUser.getUserId(), SonHaiBattleLogTypeEnum.PVP.getType(), null, resp.getReward(), resp.getAddScore(), resp.getAddAuraScore(), resp.getLoseAuraScore());
            }
            //增加山海灵气
            if (resp.getAddAuraScore() > 0) {
                team.changeAuraScore(user, resp.getAddAuraScore());
            }
            //同步队友游戏服队伍积分变更
            team.syncTeamUserScore();
            //同步地块变更
            this.syncNormalPlotChange(user, plotData);
            //战斗日志
            this.addFightLog(user, plotData, resp, costEnergy, regionData);
            //同步队友用奖励可领取红点
            if (resp.isWinFlag() && plotData.getUserId() != userId) {
                CrossSonHaiUser teamUser = this.getUser(plotData.getUserId());
                if (teamUser != null) {
                    teamUser.syncRedDotMsg(SonHaiRedDotTypeEnum.TYPE_NULL, SonHaiRedDotTypeEnum.TYPE_HAVE, SonHaiRedDotTypeEnum.TYPE_NULL);
                }
            }
            //返回
            return resp;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-PVP战斗-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            this.getLock().unlock();
        }
    }

    /**
     * boss战斗
     * @param userId
     * @param regionId
     * @return
     * @throws BusinessException
     */
    public SonHaiNewBattleResp bossBattle(long userId, int regionId) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-boss战斗-加锁-队伍-超时：{}, {}", userId, regionId);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //获取玩家区域
            if (user.getRegionData() == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
            }
            //判断玩家是否死亡
            if (user.getDieFlag() == SonHaiDieFlagEnum.DIE_YES.getType()) {
                this.syncUserData(userId, false);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_DIE);
            }
            //获取区域
            SonHaiRegionData regionData = team.getRegion(regionId);
            if (regionData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
            }
            //区域配置
            SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(regionId);
            if (floorConfig == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
            }
            //判断区域寻踪进度是否满足
            int needProgress = this.sonHaiConfig.getRegionNeedProgress(regionId);
            if (regionData.getProgress() < needProgress) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PROGRESS_NOT_ENOUGH);
            }
            //获取boss
            SonHaiBeastBossData bossData = regionData.getBeastBoss();
            if (bossData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_BEAST_BOSS_NOT_FOUND);
            }
            //判断地块是否被镇伏
            if (bossData.getWinFlag() == SonHaiWinFlagEnum.WIN_YES.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_ALREADY_WIN);
            }
            //check体力 and 消耗体力
            int costEnergy = this.checkAttackedSelfForBoss(user, bossData);
            //战斗
            SonHaiNewBattleResp resp = user.doBossBattle(bossData, regionData);
            if (resp.isWinFlag()) {
                //镇伏最高区域更新
                if (regionData.getRegionId() > team.getMaxRegionId()) {
                    team.setMaxRegionId(regionData.getRegionId());
                }
                //增加山海灵气
                if (resp.getAddAuraScore() > 0) {
                    team.changeAuraScore(user, resp.getAddAuraScore());
                }
            }
            //同步队友游戏服队伍积分变更
            team.syncTeamUserScore();
            //同步队友地块变更
            this.syncNormalPlotChange(user, regionData.getBossPlotDataList());
            //战斗日志
            List<SonHaiPlotData> plotDataList = regionData.getPlotDataListByType(SonHaiPlotTypeEnum.PLOT_TYPE_1.getType());
            this.addFightLog(user, plotDataList.get(0), resp, costEnergy, regionData);
            //返回
            return resp;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-boss战斗-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * 兽蛋战斗
     * @param userId
     * @param x
     * @param y
     * @param patronsMap
     * @return
     * @throws BusinessException
     */
    public SonHaiBattleResp eggBattle(long userId, int regionId, int x, int y, Map<Integer, SonHaiPatronsData> patronsMap) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        try {
            //加锁-活动，设置5秒超时
            if (!this.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-兽蛋战斗-加锁-活动-超时：{}, {}, {}, {}, {}", userId, regionId, x, y, patronsMap);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //获取玩家
            CrossSonHaiUser user = this.getUser(userId);
            if (user == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
            }
            //获取玩家区域
            if (user.getRegionData() == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
            }
            //判断玩家是否死亡
            if (user.getDieFlag() == SonHaiDieFlagEnum.DIE_YES.getType()) {
                this.syncUserData(userId, false);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_DIE);
            }
            //获取队伍
            CrossSonHaiTeam team = this.getTeam(user.getTeamId());
            if (team == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
            }
            //获取区域
            SonHaiRegionData regionData = team.getRegion(regionId);
            if (regionData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
            }
            //获取地块
            SonHaiPlotData plotData = regionData.getPlotData(x, y);
            if (plotData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_NOT_FOUND);
            }
            //判断地块是否被镇伏
            if (plotData.getWinFlag() == SonHaiWinFlagEnum.WIN_YES.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_ALREADY_WIN);
            }
            //判断地块是否被封锁
            boolean lockFlag = regionData.checkPlotLock(plotData.getX(), plotData.getY(), this.sonHaiConfig);
            if (lockFlag) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_LOCK);
            }
            //判断兽蛋是否存在
            SonHaiEggData eggData = this.getEgg(plotData.getEggId());
            if (eggData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EGG_NOT_FOUND);
            }
            //判断兽蛋是否被队友占领
            if (team.getMemberMap().containsKey(eggData.getUserId())) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EGG_ALREADY_WIN);
            }
            //判断门客id是否合法
            if (patronsMap.size() != 5) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_BATTLE_SELECT_PATRONS_ERROR);
            }
//            //判断门客是否已经在驻守蛋蛋
//            Map<Integer, SonHaiPatronsEgg> inEggPatronsMap = this.getInEggPatronsMap(userId);
//            for (SonHaiPatronsData patronsData : patronsMap.values()) {
//                if (inEggPatronsMap.containsKey(patronsData.getPatronsId())) {
//                    throw BusinessException.newException(GameErrorCode.E_SON_HAI_PATRONS_ALREADY_IN_EGG);
//                }
//            }
            //战力转换
            this.transformPatronsPower(patronsMap);

            //获取下占领兽蛋的玩家
            CrossSonHaiUser targetUser = null;
            long targetUserId = 0;
            if (eggData.getUserId() > 0) {
                targetUser = this.userMap.get(eggData.getUserId());
                targetUserId = eggData.getUserId();
            }
            //是打自己的还是打队友的
            int costEnergy;
            if (plotData.getUserId() == userId) {
                //打自己的
                costEnergy = this.checkAttackedSelfForPlot(user, plotData);
            } else {
                //协助队友的
                costEnergy = this.checkAttackedTeamMemberForEgg(user, eggData);
            }
            //战斗
            SonHaiBattleResp resp = user.doEggBattle(patronsMap, regionData, plotData, eggData, targetUser);
            //同步队友游戏服队伍积分变更
            team.syncTeamUserScore();
            //同步地块变更
            this.syncNormalPlotChange(user, plotData);
            //EGG战斗日志
            if (resp.isWinFlag() && targetUser != null) {
                this.addBattleLog(plotData.getType(), userId, targetUser.getUserId(), SonHaiBattleLogTypeEnum.EGG.getType(), eggData, null, 0, 0, 0);
            }
            //战斗日志
            this.addFightLog(user, plotData, resp, costEnergy, regionData);
            //兽蛋争夺日志
            if (resp.isWinFlag()) {
                LogCrossSonHaiEgg log = new LogCrossSonHaiEgg(
                        this.activityData.getActivityId(),
                        this.groupId,
                        eggData.getId(),
                        eggData.getEggConfigId(),
                        userId,
                        targetUserId,
                        user.getTeamId()
                );
                CrossAutoLogMgr.add(log);
            }
            //返回
            return resp;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-抢蛋战斗-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            this.getLock().unlock();
        }
    }

    /**
     * 获取蛋奖励
     * @param userId
     * @return
     * @throws BusinessException
     */
    public List<SonHaiUserEggRewardData> getEggRewardList(long userId) throws BusinessException {
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        Map<Integer, SonHaiUserEggRewardData> map = user.getUserEggRewardDataMap();
        //过滤下已经领取的
        List<SonHaiUserEggRewardData> list = new ArrayList<>();
        for (SonHaiUserEggRewardData item : map.values()) {
            if (item.getRewardFlag() == SonHaiRewardFlagEnum.GET_NOT.getType()) {
                list.add(item);
            }
        }
        return list;
    }

    /**
     * 领取兽蛋孵化奖励
     * @param userId
     * @return String
     * @throws BusinessException
     */
    public String receiveEggReward(long userId, int eggRewardId) throws BusinessException {
        //通用检测
        this.commonCheck(false, false);
        try {
            //加锁-活动，设置5秒超时
            if (!this.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-领取兽蛋孵化奖励-加锁-活动-超时：{}, {}", userId, eggRewardId);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //获取玩家
            CrossSonHaiUser user = this.getUser(userId);
            if (user == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
            }
            //获取玩家区域
            if (user.getRegionData() == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
            }
            //判断兽蛋奖励是否存在
            SonHaiUserEggRewardData eggRewardData = user.getUserEggRewardData(eggRewardId);
            if (eggRewardData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EGG_REWARD_NOT_FOUND);
            }
            //判断是否已经领取
            if (eggRewardData.getRewardFlag() == SonHaiRewardFlagEnum.GET_YES.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EGG_REWARD_ALREADY_RECEIVE);
            }
            //更新蛋的领取状态
            eggRewardData.setRewardFlag(SonHaiRewardFlagEnum.GET_YES.getType());
            eggRewardData.setRewardTime(System.currentTimeMillis());
            //获取蛋的奖励
            return eggRewardData.getReward();
        } catch (InterruptedException e) {
            logger.error("山海伏兽-领取兽蛋破壳奖励-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            this.getLock().unlock();
        }
    }

    /**
     * 离开区域，进入另一个区域
     * @param userId 玩家ID
     * @param regionId 区域ID
     * @return
     * @throws BusinessException
     */
    public void enterRegion(long userId, int regionId) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-离开区域，进入另一个区域-加锁-队伍-超时：{}, {}", userId, regionId);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //判断区域ID是否合法,是否在配置区域里
            SonHaiFloorConfig floorConfig = this.sonHaiConfig.getFloorConfig(regionId);
            if (floorConfig == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
            }
//            //获取默认第一个区域
//            int firstRegionId = this.sonHaiConfig.getFirstDiffTypeRegionId(floorConfig.getDiffType());
//            if (firstRegionId <= 0) {
//                throw BusinessException.newException(GameErrorCode.E_SON_HAI_ENTER_REGION_ERROR);
//            }
//            if (firstRegionId != regionId) {
//                //判断上一个区域是否通过
//                int diffTypeMaxRegionId = team.getDiffTypeMaxRegionId(floorConfig.getDiffType());
//                if (diffTypeMaxRegionId + 1 < regionId) {
//                    throw BusinessException.newException(GameErrorCode.E_SON_HAI_ENTER_REGION_ERROR);
//                }
//            }
            //获取当前区域
            SonHaiRegionData oldRegionData = user.getRegionData();

            //判断进入的区域是否合法
            int defaultRegionId = this.sonHaiConfig.getDefaultRegionId();
            if (regionId != defaultRegionId && regionId > (team.getMaxRegionId() + 1)) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_ENTER_REGION_ERROR);
            }

            //获取新区域
            SonHaiRegionData regionData = team.getRegion(regionId);
            //判断区域是否存在
            if (regionData == null) {
                //区域不存在，创建区域
                regionData = this.createRegion(team.getTeamId(), regionId);
                //set新区域
                team.addRegion(regionData);
            }

            //推送其他对应。玩家离开区域
            if (oldRegionData != null && oldRegionData.getRegionId() != regionId) {
                for (CrossSonHaiUser member : team.getMemberMap().values()) {
                    if (member.getUserId() != userId && member.getRegionId() == oldRegionData.getRegionId()) {
                        //旧区域，推送玩家离开该区域
                        SonHaiProto.SonHaiSyncUserPositionChangeMsg.Builder  builder = SonHaiProto.SonHaiSyncUserPositionChangeMsg.newBuilder();
                        builder.setActivityId(this.activityData.getActivityId());
                        builder.setUserId(userId);
                        builder.setX(-1);
                        builder.setY(-1);
                        MessageHelper.sendPacket(member.getServerId(), member.getUserId(), YanQuMessageUtils.buildMessage(Protocol.U_SON_HAI_SYNC_USER_POSITION_CHANGE, builder));
                    }
                }
            }

            //玩家注入区域
            SonHaiPlotData beastBossPlot = regionData.getBeastKingPlot();
            user.setRegionAndPosition(regionData, beastBossPlot.getX(), beastBossPlot.getY());
            if (user.getSelectRegionFlag() == SonHaiYNEnum.NOT.getType()) {
                user.setSelectRegionFlag(SonHaiYNEnum.YES.getType());
            }

            //是否有投票单
            if (oldRegionData != null && oldRegionData.getLaunchRestUserId() > 0) {
                //移除同意投票
                oldRegionData.removeAgreeRestUserIds(userId);
                //同步重置区域投票有人离开
                this.syncRestRegionOrder(oldRegionData, team, 0);
                //判断区域是否还有人
                Set<Long> regionUserIds = team.getRegionUserIds(oldRegionData.getRegionId());
                if (regionUserIds.isEmpty()) {
                    //取消投票单
                    oldRegionData.setLaunchRestUserId(0);
                    oldRegionData.setAutoRestTime(0);
                    oldRegionData.setAgreeRestUserIds(new HashSet<>());
                } else {
                    //剩下的这几个人都同意，直接重置
                    int regionsUserNum = regionUserIds.size();
                    regionUserIds.retainAll(oldRegionData.getAgreeRestUserIds());//求交集
                    if (regionsUserNum == regionUserIds.size()) {
                        //直接重置
                        this.doRestRegion(oldRegionData, team);
                    }
                }
            }
            if (regionData.getLaunchRestUserId() > 0) {
                //同步重置区域投票有人进入
                this.syncRestRegionOrder(regionData, team, 0);
            }

        } catch (InterruptedException e) {
            logger.error("山海伏兽-离开区域，进入另一个区域-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * 重置区域-2024-09-02 旧重置区域方法废弃，该成投票重置
     * @param userId 玩家ID
     * @return
     * @throws BusinessException
     */
    public void restRegion(long userId) throws BusinessException {
//        //通用检测
//        this.commonCheck(true, true);
//        //获取玩家
//        CrossSonHaiUser user = this.getUser(userId);
//        if (user == null) {
//            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
//        }
//        //获取队伍
//        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
//        if (team == null) {
//            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
//        }
//        try {
//            //加锁-队伍，设置5秒超时
//            if (!team.getLock().tryLock( 5, TimeUnit.SECONDS)) {
//                logger.error("山海伏兽-重置区域-加锁-队伍-超时：{}", userId);
//                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
//            }
//            //获取区域
//            SonHaiRegionData oldRegionData = user.getRegionData();
//            //重置区域
//            this.doRestRegion(oldRegionData, team);
//        } catch (InterruptedException e) {
//            logger.error("山海伏兽-重置区域-tryLock报错：{}", e);
//            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
//        } finally {
//            team.getLock().unlock();
//        }
    }

    /**
     * 重置区域
     * @param oldRegionData
     * @param team
     * @throws BusinessException
     */
    public void doRestRegion(SonHaiRegionData oldRegionData, CrossSonHaiTeam team) throws BusinessException {
        //获取区域
        if (oldRegionData == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
        }
        //判断boss是否镇伏
        if (oldRegionData.getBeastBoss().getWinFlag() != SonHaiWinFlagEnum.WIN_YES.getType()) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_BOSS_NOT_WIN);
        }
        //判断是否有重置投票单
        if (oldRegionData.getLaunchRestUserId() <= 0) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_NOT_REST_REGION);
        }
        //判断旧区域是否存在
        if (!team.getRegionMap().containsKey(oldRegionData.getRegionId())) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
        }

        //重新生成区域
        SonHaiRegionData newRegionData = this.createRegion(team.getTeamId(), oldRegionData.getRegionId());

        //移除旧区域
        team.removeRegion(oldRegionData.getRegionId());

        //set新区域
        team.addRegion(newRegionData);

        //玩家注入区域
        SonHaiPlotData beastBossPlot = newRegionData.getBeastKingPlot();
        for (CrossSonHaiUser member : team.getMemberMap().values()) {
            //在这个区域里的玩家，重新进入区域
            if (member.getRegionId() == oldRegionData.getRegionId()) {
                member.setRegionAndPosition(newRegionData, beastBossPlot.getX(), beastBossPlot.getY());
                //同步在该区域的其他队友，刷一下区域
                this.pushRegionResetMsg(member.getUserId(), oldRegionData.getLaunchRestUserId());
            }
        }

        //重置区域日志
        LogCrossSonHaiResetRegion log = new LogCrossSonHaiResetRegion(
                this.activityData.getActivityId(),
                this.groupId,
                oldRegionData.getLaunchRestUserId(),
                team.getTeamId(),
                oldRegionData.getRegionId()
        );
        CrossAutoLogMgr.add(log);
    }

    /**
     * 选择BUFF
     * @param userId
     * @param buffId
     * @throws BusinessException
     */
    public void selectBuff(long userId, int buffId) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取玩家区域
        if (user.getRegionData() == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-选择BUFF-加锁-队伍-超时：{}, {}", userId, buffId);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //选择buff
            user.selectBuff(buffId);
            //buff操作日志
            LogCrossSonHaiSelectBuff log = new LogCrossSonHaiSelectBuff(
                    this.activityData.getActivityId(),
                    this.groupId,
                    userId,
                    user.getTeamId(),
                    user.getBuffComeNum(),
                    SonHaiLogSelectBuffOpTypeEnum.SELECT.getType(),
                    buffId,
                    0
            );
            CrossAutoLogMgr.add(log);
        } catch (InterruptedException e) {
            logger.error("山海伏兽-选择BUFF-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * 日志-探险互助
     * @param userId
     * @return
     * @throws BusinessException
     */
    public List<SonHaiPlotData> getNormalBattleLogList(long userId) throws BusinessException {
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        return team.getNormalBattleLogList(userId);
    }

    /**
     * 日志-兽王踪迹
     * @param userId
     * @return
     * @throws BusinessException
     */
    public List<SonHaiBeastBossData> getBossBattleLogList(long userId) throws BusinessException {
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        return team.getBossBattleLogList(userId);
    }

    /**
     * 日志-兽蛋共享
     * @param userId
     * @return
     * @throws BusinessException
     */
    public List<SonHaiPlotData> getEggBattleLogList(long userId) throws BusinessException {
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        return team.getEggBattleLogList(userId);
    }

    /**
     * 领取镇伏奖励
     * @param userId 玩家ID
     * @return
     * @throws BusinessException
     */
    public SonHaiRewardResp receiveWinReward(long userId, int x, int y) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-领取镇伏奖励-加锁-队伍-超时：{}, {}, {}", userId, x, y);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //领取
            SonHaiRewardResp resp = user.receiveWinReward(x, y);
            //增加山海灵气
            if (resp.getAddAuraScore() > 0) {
                team.changeAuraScore(user, resp.getAddAuraScore());
            }
            return resp;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-领取镇伏奖励-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * 领取镇伏奖励（兽王）
     * @param userId 玩家ID
     * @return
     * @throws BusinessException
     */
    public SonHaiRewardResp receiveBossWinReward(long userId, int regionId) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-领取镇伏奖励（兽王）-加锁-队伍-超时：{}，{}", userId, regionId);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //获取区域
            SonHaiRegionData regionData = team.getRegion(regionId);
            if (regionData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REGION_NOT_FOUND);
            }
            //领取
            SonHaiRewardResp resp = user.receiveBossWinReward(regionData);
            //增加山海灵气
            if (resp.getAddAuraScore() > 0) {
                team.changeAuraScore(user, resp.getAddAuraScore());
            }
            return resp;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-领取镇伏奖励（兽王）-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * 使用道具恢复体力
     * @param userId
     * @param propId
     * @param num
     * @throws BusinessException
     */
    public void usePropRecoverEnergy(long userId, int propId, int num) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-使用道具恢复体力-加锁-队伍-超时：{}, {}, {}", userId, propId, num);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //使用道具恢复体力
            user.usePropRecoverEnergy(propId, num);
        } catch (InterruptedException e) {
            logger.error("山海伏兽-使用道具恢复体力-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * 获取队伍玩家所在区域MAP
     * @param userId
     * @return
     * @throws BusinessException
     */
    public Map<Integer, SonHaiRegionUserResp> getRegionMap(long userId) {
        Map<Integer, SonHaiRegionUserResp> map = new HashMap<>();
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
           return map;
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            return map;
        }
        //战力未生成
        if (this.activityData.getVipAvePowerMap() == null || this.activityData.getVipAvePowerMap().isEmpty()) {
            return map;
        }
        //遍历区域
        for (SonHaiFloorConfig floorConfig : this.sonHaiConfig.getFloorConfigMap().values()) {
            SonHaiRegionUserResp resp = new SonHaiRegionUserResp();
            resp.setRegionId(floorConfig.getId());
            for (CrossSonHaiUser member : team.getMemberMap().values()) {
                if (member.getRegionId() == floorConfig.getId()) {
                    resp.addUserId(member.getUserId());
                }
            }
            long power = this.createBeastPower(floorConfig.getPower(), floorConfig.getId());
            resp.setPower(power);
            map.put(floorConfig.getId(), resp);
        }
        return map;
    }

    /**
     * 获取争夺日志
     * @param pageNum
     * @param pageSize
     * @param userId
     * @return
     * @throws BusinessException
     */
    public List<SonHaiBattleLog> getBattleLogList(int pageNum, int pageSize, long userId) {
        FixSizeLinkedList<SonHaiBattleLog> result = new FixSizeLinkedList<>(100);
        if (userId > 0) {
            //玩家维度日志
            CrossSonHaiUser user = this.getUser(userId);
            if (user != null) {
                result = user.getBattleLogList();
            }
        } else {
            //活动维度日志
            result = this.battleLogList;
        }
        //分页一下
        return result.getPage(pageNum, pageSize);
    }

    /**
     * 唤醒
     * @param userId
     * @throws BusinessException
     */
    public void wakeUp(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        try {
            //加锁-活动，设置5秒超时
            if (!this.getLock().tryLock( 5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-唤醒-加锁-活动-超时：{}, {}", userId);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //获取玩家
            CrossSonHaiUser user = this.getUser(userId);
            if (user == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
            }
            //获取玩家区域
            if (user.getRegionData() == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
            }
            //判断是否死亡
            if (user.getDieFlag() != SonHaiDieFlagEnum.DIE_YES.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_WAKE_UP_NOT_DIE);
            }
            user.wakeUp();
        } catch (InterruptedException e) {
            logger.error("山海伏兽-唤醒-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            this.getLock().unlock();
        }
    }

    /**
     * 重新随机待选择BUFF LIST
     * @param userId
     * @throws BusinessException
     */
    public void resetRandomSelectBuff(long userId) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取玩家区域
        if (user.getRegionData() == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
        }
        user.resetRandomSelectBuff();
    }

     /**
     * 2选1-选择奖励
     * @param userId
     * @param x
     * @param y
     * @param rightOrWrong
     * @return
     * @throws BusinessException
     */
    public SonHaiChooseResp receiveChooseEventReward(long userId, int x, int y, int rightOrWrong) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock(5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-2选1-加锁-队伍-超时：{}, {}, {}, {}", userId, x, y, rightOrWrong);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //获取玩家区域
            SonHaiRegionData regionData = user.getRegionData();
            if (regionData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
            }
            //获取地块
            SonHaiPlotData plotData = regionData.getPlotData(x, y);
            if (plotData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_NOT_FOUND);
            }
            //判断地块事件是2选1事件
            SonHaiEventConfig eventConfig = this.sonHaiConfig.getEventConfig(plotData.getPlotId());
            if (eventConfig == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_EVENT_NOT_EXIST);
            }
            if (eventConfig.getEventType() != SonHaiPlotTypeEnum.PLOT_TYPE_16.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_PLOT_TYPE_ERROR);
            }
            //判断奖励是否选择过
            if (plotData.getChooseRewardFlag() != SonHaiRewardFlagEnum.GET_NOT.getType()) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REWARD_ALREADY_RECEIVE);
            }
            //奖励
            String reward = eventConfig.getChooseReward(rightOrWrong);
            //记录领取状态
            plotData.setChooseRewardFlag(SonHaiRewardFlagEnum.GET_YES.getType());
            //封装结果
            SonHaiChooseResp resp = new SonHaiChooseResp();
            resp.setReward(reward);
            resp.setChooseConfigId(eventConfig.getId());
            resp.setIndex(eventConfig.getChooseTrueIndex());
            resp.setChooseTrue(rightOrWrong > 0);
            return resp;
        } catch (InterruptedException e) {
            logger.error("山海伏兽-2选1-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * 接收到占领兽蛋被抢推送
     */
    public void acceptOccupyEggBeTakenMsg(long userId, List<Integer> eggIds) throws BusinessException {
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        for (int eggId : eggIds) {
            user.removeLostEgg(eggId);
        }
    }

    /**
     * 获取区域数据
     * @param teamId
     * @param regionId
     * @return
     */
    public SonHaiRegionData getRegionData(int teamId, int regionId) {
        CrossSonHaiTeam team = teamMap.get(teamId);
        if (team != null) {
            return team.getRegion(regionId);
        }
        return null;
    }

    /**
     * 同意/拒绝重置区域
     * @param userId
     * @param type
     * @throws BusinessException
     */
    public void opRestRegion(long userId, int type) throws BusinessException {
        //通用检测
        this.commonCheck(true, true);
        //获取玩家
        CrossSonHaiUser user = this.getUser(userId);
        if (user == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_USER_NOT_FOUND);
        }
        //获取队伍
        CrossSonHaiTeam team = this.getTeam(user.getTeamId());
        if (team == null) {
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_TEAM_NOT_FOUND);
        }
        try {
            //加锁-队伍，设置5秒超时
            if (!team.getLock().tryLock(5, TimeUnit.SECONDS)) {
                logger.error("山海伏兽-同意/拒绝重置区域-超时：{}, {}, {}, {}", userId, type);
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
            }
            //获取玩家区域
            SonHaiRegionData regionData = user.getRegionData();
            if (regionData == null) {
                throw BusinessException.newException(GameErrorCode.E_SON_HAI_SELF_REGION_NOT_FOUND);
            }
            //判断是发起还是其他
            if (type == SonHaiOpRestRegionTypeEnum.OFFER.getType()) {
                //判断boss是否镇伏
                if (regionData.getBeastBoss().getWinFlag() != SonHaiWinFlagEnum.WIN_YES.getType()) {
                    throw BusinessException.newException(GameErrorCode.E_SON_HAI_BOSS_NOT_WIN);
                }
                //判断区域是有发起投票
                if (regionData.getLaunchRestUserId() > 0) {
                    throw BusinessException.newException(GameErrorCode.E_SON_HAI_ALREADY_REST_REGION);
                }
            } else {
                //判断区域是有发起投票
                if (regionData.getLaunchRestUserId() <= 0) {
                    throw BusinessException.newException(GameErrorCode.E_SON_HAI_NOT_REST_REGION);
                }
                //判断重置区域投票是否超时
                if (System.currentTimeMillis() >= regionData.getAutoRestTime()) {
                    throw BusinessException.newException(GameErrorCode.E_SON_HAI_NOT_REST_REGION);
                }
            }
            //区域里的玩家ID
            Set<Long> userIds = team.getRegionUserIds(regionData.getRegionId());

            //发起/同意/拒绝
            if (type == SonHaiOpRestRegionTypeEnum.OFFER.getType()) {
                //发起，生成投票单
                int autoRestSecond = this.sonHaiConfig.getResetAgreeTime();
                regionData.setAutoRestTime(System.currentTimeMillis() + autoRestSecond * 1000L);
                regionData.setLaunchRestUserId(userId);
                regionData.addAgreeRestUserIds(userId);
                //判断是否就自己一个人
                if (userIds.size() <= 1 && userIds.contains(userId)) {
                    //区域就自己一个人，直接重置
                    this.doRestRegion(regionData, team);
                } else {
                    //同步
                    this.syncRestRegionOrder(regionData, team, 0);
                }
            } else if (type == SonHaiOpRestRegionTypeEnum.AGREE.getType()) {
                //同意
                regionData.addAgreeRestUserIds(userId);
                //同步
                this.syncRestRegionOrder(regionData, team, 0);
                //判断同意人数是否达到
                if (regionData.getAgreeRestUserIds().size() >= userIds.size()) {
                    //重置
                    this.doRestRegion(regionData, team);
                }
            } else if (type == SonHaiOpRestRegionTypeEnum.REJECT.getType()) {
                //拒绝
                regionData.setLaunchRestUserId(0);
                regionData.setAutoRestTime(0);
                regionData.setAgreeRestUserIds(new HashSet<>());
                //同步
                this.syncRestRegionOrder(regionData, team, userId);
            } else if (type == SonHaiOpRestRegionTypeEnum.CANCEL_AGREE.getType()) {
                //取消同意
                regionData.removeAgreeRestUserIds(userId);
                //同步
                this.syncRestRegionOrder(regionData, team, 0);
            }
        } catch (InterruptedException e) {
            logger.error("山海伏兽-同意/拒绝重置区域-tryLock报错：{}", e);
            throw BusinessException.newException(GameErrorCode.E_SON_HAI_REQUEST_TIME_OUT);
        } finally {
            team.getLock().unlock();
        }
    }

    /**
     * 同步投票单
     * @param regionData
     * @param team
     * @param rejectUserId 拒绝的玩家ID
     */
    public void syncRestRegionOrder(SonHaiRegionData regionData, CrossSonHaiTeam team, long rejectUserId) {
        //区域里的玩家
        Set<Long> userIds = team.getRegionUserIds(regionData.getRegionId());
        //同步
        SonHaiProto.SonHaiSyncResetRegionOrderMsg.Builder builder = SonHaiProto.SonHaiSyncResetRegionOrderMsg.newBuilder();
        builder.setRegionId(regionData.getRegionId());
        builder.setLaunchUserId(regionData.getLaunchRestUserId());
        builder.addAllUserIds(userIds);
        builder.addAllAgreeUserIds(regionData.getAgreeRestUserIds());
        builder.setAutoRestTime(regionData.getAutoRestTime());
        builder.setReject(rejectUserId > 0);
        builder.setRejectUserId(rejectUserId);
        for (long userId : userIds) {
            CrossSonHaiUser user = team.getMemberMap().get(userId);
            if (user != null) {
                MessageHelper.sendPacket(user.getServerId(), userId, YanQuMessageUtils.buildMessage(Protocol.U_SON_HAI_SYNC_REST_REGION_ORDER_MSG, builder));
            }
        }
    }

    /**
     * 重置区域定时任务
     * @throws BusinessException
     */
    public void doRestRegionTask() {
        for (CrossSonHaiTeam team : this.teamMap.values()) {
            //重置
            try {
                //加锁-队伍，设置5秒超时
                if (!team.getLock().tryLock(5, TimeUnit.SECONDS)) {
                    logger.error("山海伏兽-重置区域定时任务-超时：{}, {}, {}, {}", team.getTeamId());
                    continue;
                }
                //遍历区域
                for (SonHaiRegionData regionData : team.getRegionMap().values()) {
                    if (regionData.getLaunchRestUserId() <= 0) {
                        continue;
                    }
                    //判断投票时间是否到达
                    if (System.currentTimeMillis() >= regionData.getAutoRestTime()) {
                        //重置
                        try {
                            this.doRestRegion(regionData, team);
                        } catch (BusinessException e) {
                            logger.error("山海伏兽-重置区域定时任务-doRestRegion：{}, {}, {}", team.getTeamId(), regionData.getRegionId(), e.getCode());
                        }
                    }
                }
            } catch (InterruptedException e) {
                logger.error("山海伏兽-重置区域定时任务-报错：{}", e);
            } finally {
                team.getLock().unlock();
            }
        }
    }
}
